Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/staging: (44 commits) hwmon: Support for Dallas Semiconductor DS620 hwmon: driver for Sensirion SHT21 humidity and temperature sensor hwmon: Add humidity attribute to sysfs ABI hwmon: sysfs ABI updates hwmon: (via-cputemp) sync hotplug handling with coretemp/pkgtemp hwmon: (lm95241) Rewrite to avoid using macros hwmon: (applesmc) Fix checkpatch errors and fix value range checks hwmon: (applesmc) Update copyright information hwmon: (applesmc) Silence driver hwmon: (applesmc) Simplify feature sysfs handling hwmon: (applesmc) Dynamic creation of fan files hwmon: (applesmc) Extract all features generically hwmon: (applesmc) Handle new temperature format hwmon: (applesmc) Dynamic creation of temperature files hwmon: (applesmc) Introduce a register lookup table hwmon: (applesmc) Use pr_fmt and pr_<level> hwmon: (applesmc) Relax the severity of device init failure hwmon: (applesmc) Add MacBookAir3,1(3,2) support hwmon: (w83627hf) Use pr_fmt and pr_<level> hwmon: (w83627ehf) Use pr_fmt and pr_<level> ...
This commit is contained in:
commit
a08948812b
34
Documentation/hwmon/ds620
Normal file
34
Documentation/hwmon/ds620
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
Kernel driver ds620
|
||||||
|
===================
|
||||||
|
|
||||||
|
Supported chips:
|
||||||
|
* Dallas Semiconductor DS620
|
||||||
|
Prefix: 'ds620'
|
||||||
|
Datasheet: Publicly available at the Dallas Semiconductor website
|
||||||
|
http://www.dalsemi.com/
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
Roland Stigge <stigge@antcom.de>
|
||||||
|
based on ds1621.c by
|
||||||
|
Christian W. Zuckschwerdt <zany@triq.net>
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The DS620 is a (one instance) digital thermometer and thermostat. It has both
|
||||||
|
high and low temperature limits which can be user defined (i.e. programmed
|
||||||
|
into non-volatile on-chip registers). Temperature range is -55 degree Celsius
|
||||||
|
to +125. Between 0 and 70 degree Celsius, accuracy is 0.5 Kelvin. The value
|
||||||
|
returned via sysfs displays post decimal positions.
|
||||||
|
|
||||||
|
The thermostat function works as follows: When configured via platform_data
|
||||||
|
(struct ds620_platform_data) .pomode == 0 (default), the thermostat output pin
|
||||||
|
PO is always low. If .pomode == 1, the thermostat is in PO_LOW mode. I.e., the
|
||||||
|
output pin PO becomes active when the temperature falls below temp1_min and
|
||||||
|
stays active until the temperature goes above temp1_max.
|
||||||
|
|
||||||
|
Likewise, with .pomode == 2, the thermostat is in PO_HIGH mode. I.e., the PO
|
||||||
|
output pin becomes active when the temperature goes above temp1_max and stays
|
||||||
|
active until the temperature falls below temp1_min.
|
||||||
|
|
||||||
|
The PO output pin of the DS620 operates active-low.
|
49
Documentation/hwmon/sht21
Normal file
49
Documentation/hwmon/sht21
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
Kernel driver sht21
|
||||||
|
===================
|
||||||
|
|
||||||
|
Supported chips:
|
||||||
|
* Sensirion SHT21
|
||||||
|
Prefix: 'sht21'
|
||||||
|
Addresses scanned: none
|
||||||
|
Datasheet: Publicly available at the Sensirion website
|
||||||
|
http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf
|
||||||
|
|
||||||
|
* Sensirion SHT25
|
||||||
|
Prefix: 'sht21'
|
||||||
|
Addresses scanned: none
|
||||||
|
Datasheet: Publicly available at the Sensirion website
|
||||||
|
http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT25.pdf
|
||||||
|
|
||||||
|
Author:
|
||||||
|
Urs Fleisch <urs.fleisch@sensirion.com>
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The SHT21 and SHT25 are humidity and temperature sensors in a DFN package of
|
||||||
|
only 3 x 3 mm footprint and 1.1 mm height. The difference between the two
|
||||||
|
devices is the higher level of precision of the SHT25 (1.8% relative humidity,
|
||||||
|
0.2 degree Celsius) compared with the SHT21 (2.0% relative humidity,
|
||||||
|
0.3 degree Celsius).
|
||||||
|
|
||||||
|
The devices communicate with the I2C protocol. All sensors are set to the same
|
||||||
|
I2C address 0x40, so an entry with I2C_BOARD_INFO("sht21", 0x40) can be used
|
||||||
|
in the board setup code.
|
||||||
|
|
||||||
|
sysfs-Interface
|
||||||
|
---------------
|
||||||
|
|
||||||
|
temp1_input - temperature input
|
||||||
|
humidity1_input - humidity input
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
The driver uses the default resolution settings of 12 bit for humidity and 14
|
||||||
|
bit for temperature, which results in typical measurement times of 22 ms for
|
||||||
|
humidity and 66 ms for temperature. To keep self heating below 0.1 degree
|
||||||
|
Celsius, the device should not be active for more than 10% of the time,
|
||||||
|
e.g. maximum two measurements per second at the given resolution.
|
||||||
|
|
||||||
|
Different resolutions, the on-chip heater, using the CRC checksum and reading
|
||||||
|
the serial number are not supported yet.
|
|
@ -384,10 +384,20 @@ curr[1-*]_min Current min value.
|
||||||
Unit: milliampere
|
Unit: milliampere
|
||||||
RW
|
RW
|
||||||
|
|
||||||
|
curr[1-*]_lcrit Current critical low value
|
||||||
|
Unit: milliampere
|
||||||
|
RW
|
||||||
|
|
||||||
|
curr[1-*]_crit Current critical high value.
|
||||||
|
Unit: milliampere
|
||||||
|
RW
|
||||||
|
|
||||||
curr[1-*]_input Current input value
|
curr[1-*]_input Current input value
|
||||||
Unit: milliampere
|
Unit: milliampere
|
||||||
RO
|
RO
|
||||||
|
|
||||||
|
Also see the Alarms section for status flags associated with currents.
|
||||||
|
|
||||||
*********
|
*********
|
||||||
* Power *
|
* Power *
|
||||||
*********
|
*********
|
||||||
|
@ -450,13 +460,6 @@ power[1-*]_accuracy Accuracy of the power meter.
|
||||||
Unit: Percent
|
Unit: Percent
|
||||||
RO
|
RO
|
||||||
|
|
||||||
power[1-*]_alarm 1 if the system is drawing more power than the
|
|
||||||
cap allows; 0 otherwise. A poll notification is
|
|
||||||
sent to this file when the power use exceeds the
|
|
||||||
cap. This file only appears if the cap is known
|
|
||||||
to be enforced by hardware.
|
|
||||||
RO
|
|
||||||
|
|
||||||
power[1-*]_cap If power use rises above this limit, the
|
power[1-*]_cap If power use rises above this limit, the
|
||||||
system should take action to reduce power use.
|
system should take action to reduce power use.
|
||||||
A poll notification is sent to this file if the
|
A poll notification is sent to this file if the
|
||||||
|
@ -479,6 +482,20 @@ power[1-*]_cap_min Minimum cap that can be set.
|
||||||
Unit: microWatt
|
Unit: microWatt
|
||||||
RO
|
RO
|
||||||
|
|
||||||
|
power[1-*]_max Maximum power.
|
||||||
|
Unit: microWatt
|
||||||
|
RW
|
||||||
|
|
||||||
|
power[1-*]_crit Critical maximum power.
|
||||||
|
If power rises to or above this limit, the
|
||||||
|
system is expected take drastic action to reduce
|
||||||
|
power consumption, such as a system shutdown or
|
||||||
|
a forced powerdown of some devices.
|
||||||
|
Unit: microWatt
|
||||||
|
RW
|
||||||
|
|
||||||
|
Also see the Alarms section for status flags associated with power readings.
|
||||||
|
|
||||||
**********
|
**********
|
||||||
* Energy *
|
* Energy *
|
||||||
**********
|
**********
|
||||||
|
@ -488,6 +505,15 @@ energy[1-*]_input Cumulative energy use
|
||||||
RO
|
RO
|
||||||
|
|
||||||
|
|
||||||
|
************
|
||||||
|
* Humidity *
|
||||||
|
************
|
||||||
|
|
||||||
|
humidity[1-*]_input Humidity
|
||||||
|
Unit: milli-percent (per cent mille, pcm)
|
||||||
|
RO
|
||||||
|
|
||||||
|
|
||||||
**********
|
**********
|
||||||
* Alarms *
|
* Alarms *
|
||||||
**********
|
**********
|
||||||
|
@ -501,6 +527,7 @@ implementation.
|
||||||
|
|
||||||
in[0-*]_alarm
|
in[0-*]_alarm
|
||||||
curr[1-*]_alarm
|
curr[1-*]_alarm
|
||||||
|
power[1-*]_alarm
|
||||||
fan[1-*]_alarm
|
fan[1-*]_alarm
|
||||||
temp[1-*]_alarm
|
temp[1-*]_alarm
|
||||||
Channel alarm
|
Channel alarm
|
||||||
|
@ -512,12 +539,20 @@ OR
|
||||||
|
|
||||||
in[0-*]_min_alarm
|
in[0-*]_min_alarm
|
||||||
in[0-*]_max_alarm
|
in[0-*]_max_alarm
|
||||||
|
in[0-*]_lcrit_alarm
|
||||||
|
in[0-*]_crit_alarm
|
||||||
curr[1-*]_min_alarm
|
curr[1-*]_min_alarm
|
||||||
curr[1-*]_max_alarm
|
curr[1-*]_max_alarm
|
||||||
|
curr[1-*]_lcrit_alarm
|
||||||
|
curr[1-*]_crit_alarm
|
||||||
|
power[1-*]_cap_alarm
|
||||||
|
power[1-*]_max_alarm
|
||||||
|
power[1-*]_crit_alarm
|
||||||
fan[1-*]_min_alarm
|
fan[1-*]_min_alarm
|
||||||
fan[1-*]_max_alarm
|
fan[1-*]_max_alarm
|
||||||
temp[1-*]_min_alarm
|
temp[1-*]_min_alarm
|
||||||
temp[1-*]_max_alarm
|
temp[1-*]_max_alarm
|
||||||
|
temp[1-*]_lcrit_alarm
|
||||||
temp[1-*]_crit_alarm
|
temp[1-*]_crit_alarm
|
||||||
temp[1-*]_emergency_alarm
|
temp[1-*]_emergency_alarm
|
||||||
Limit alarm
|
Limit alarm
|
||||||
|
|
|
@ -274,6 +274,16 @@ config SENSORS_ATXP1
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called atxp1.
|
will be called atxp1.
|
||||||
|
|
||||||
|
config SENSORS_DS620
|
||||||
|
tristate "Dallas Semiconductor DS620"
|
||||||
|
depends on I2C
|
||||||
|
help
|
||||||
|
If you say yes here you get support for Dallas Semiconductor
|
||||||
|
DS620 sensor chip.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called ds620.
|
||||||
|
|
||||||
config SENSORS_DS1621
|
config SENSORS_DS1621
|
||||||
tristate "Dallas Semiconductor DS1621 and DS1625"
|
tristate "Dallas Semiconductor DS1621 and DS1625"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
@ -734,6 +744,16 @@ config SENSORS_SHT15
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called sht15.
|
will be called sht15.
|
||||||
|
|
||||||
|
config SENSORS_SHT21
|
||||||
|
tristate "Sensiron humidity and temperature sensors. SHT21 and compat."
|
||||||
|
depends on I2C
|
||||||
|
help
|
||||||
|
If you say yes here you get support for the Sensiron SHT21, SHT25
|
||||||
|
humidity and temperature sensors.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called sht21.
|
||||||
|
|
||||||
config SENSORS_S3C
|
config SENSORS_S3C
|
||||||
tristate "Samsung built-in ADC"
|
tristate "Samsung built-in ADC"
|
||||||
depends on S3C_ADC
|
depends on S3C_ADC
|
||||||
|
|
|
@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
|
||||||
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
|
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
|
||||||
obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o
|
obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o
|
||||||
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
|
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
|
||||||
|
obj-$(CONFIG_SENSORS_DS620) += ds620.o
|
||||||
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
|
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
|
||||||
obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
|
obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
|
||||||
obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o
|
obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o
|
||||||
|
@ -90,6 +91,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
|
||||||
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
|
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
|
||||||
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
|
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
|
||||||
obj-$(CONFIG_SENSORS_SHT15) += sht15.o
|
obj-$(CONFIG_SENSORS_SHT15) += sht15.o
|
||||||
|
obj-$(CONFIG_SENSORS_SHT21) += sht21.o
|
||||||
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
|
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
|
||||||
obj-$(CONFIG_SENSORS_SMM665) += smm665.o
|
obj-$(CONFIG_SENSORS_SMM665) += smm665.o
|
||||||
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
|
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because
|
the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because
|
||||||
of lack of specs the CPU/RAM voltage & frequency control is not supported!
|
of lack of specs the CPU/RAM voltage & frequency control is not supported!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -220,6 +223,10 @@ struct abituguru_data {
|
||||||
u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5];
|
u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *never_happen = "This should never happen.";
|
||||||
|
static const char *report_this =
|
||||||
|
"Please report this to the abituguru maintainer (see MAINTAINERS)";
|
||||||
|
|
||||||
/* wait till the uguru is in the specified state */
|
/* wait till the uguru is in the specified state */
|
||||||
static int abituguru_wait(struct abituguru_data *data, u8 state)
|
static int abituguru_wait(struct abituguru_data *data, u8 state)
|
||||||
{
|
{
|
||||||
|
@ -438,8 +445,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
|
||||||
|
|
||||||
/* Test val is sane / usable for sensor type detection. */
|
/* Test val is sane / usable for sensor type detection. */
|
||||||
if ((val < 10u) || (val > 250u)) {
|
if ((val < 10u) || (val > 250u)) {
|
||||||
printk(KERN_WARNING ABIT_UGURU_NAME
|
pr_warn("bank1-sensor: %d reading (%d) too close to limits, "
|
||||||
": bank1-sensor: %d reading (%d) too close to limits, "
|
|
||||||
"unable to determine sensor type, skipping sensor\n",
|
"unable to determine sensor type, skipping sensor\n",
|
||||||
(int)sensor_addr, (int)val);
|
(int)sensor_addr, (int)val);
|
||||||
/* assume no sensor is there for sensors for which we can't
|
/* assume no sensor is there for sensors for which we can't
|
||||||
|
@ -535,10 +541,8 @@ abituguru_detect_bank1_sensor_type_exit:
|
||||||
3) == 3)
|
3) == 3)
|
||||||
break;
|
break;
|
||||||
if (i == 3) {
|
if (i == 3) {
|
||||||
printk(KERN_ERR ABIT_UGURU_NAME
|
pr_err("Fatal error could not restore original settings. %s %s\n",
|
||||||
": Fatal error could not restore original settings. "
|
never_happen, report_this);
|
||||||
"This should never happen please report this to the "
|
|
||||||
"abituguru maintainer (see MAINTAINERS)\n");
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1268,14 +1272,12 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
/* Fail safe check, this should never happen! */
|
/* Fail safe check, this should never happen! */
|
||||||
if (sysfs_names_free < 0) {
|
if (sysfs_names_free < 0) {
|
||||||
printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of "
|
pr_err("Fatal error ran out of space for sysfs attr names. %s %s",
|
||||||
"space for sysfs attr names. This should never "
|
never_happen, report_this);
|
||||||
"happen please report to the abituguru maintainer "
|
|
||||||
"(see MAINTAINERS)\n");
|
|
||||||
res = -ENAMETOOLONG;
|
res = -ENAMETOOLONG;
|
||||||
goto abituguru_probe_error;
|
goto abituguru_probe_error;
|
||||||
}
|
}
|
||||||
printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
|
pr_info("found Abit uGuru\n");
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
/* Register sysfs hooks */
|
||||||
for (i = 0; i < sysfs_attr_i; i++)
|
for (i = 0; i < sysfs_attr_i; i++)
|
||||||
|
@ -1432,8 +1434,7 @@ static int __init abituguru_detect(void)
|
||||||
"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
|
"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
|
||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is "
|
pr_info("Assuming Abit uGuru is present because of \"force\" parameter\n");
|
||||||
"present because of \"force\" parameter\n");
|
|
||||||
return ABIT_UGURU_BASE;
|
return ABIT_UGURU_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1467,8 +1468,7 @@ static int __init abituguru_init(void)
|
||||||
|
|
||||||
abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address);
|
abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address);
|
||||||
if (!abituguru_pdev) {
|
if (!abituguru_pdev) {
|
||||||
printk(KERN_ERR ABIT_UGURU_NAME
|
pr_err("Device allocation failed\n");
|
||||||
": Device allocation failed\n");
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto exit_driver_unregister;
|
goto exit_driver_unregister;
|
||||||
}
|
}
|
||||||
|
@ -1479,15 +1479,13 @@ static int __init abituguru_init(void)
|
||||||
|
|
||||||
err = platform_device_add_resources(abituguru_pdev, &res, 1);
|
err = platform_device_add_resources(abituguru_pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR ABIT_UGURU_NAME
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
": Device resource addition failed (%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(abituguru_pdev);
|
err = platform_device_add(abituguru_pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR ABIT_UGURU_NAME
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
": Device addition failed (%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
chip found on newer Abit uGuru motherboards. Note: because of lack of specs
|
chip found on newer Abit uGuru motherboards. Note: because of lack of specs
|
||||||
only reading the sensors and their settings is supported.
|
only reading the sensors and their settings is supported.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -608,6 +611,9 @@ static int verbose = 1;
|
||||||
module_param(verbose, bool, 0644);
|
module_param(verbose, bool, 0644);
|
||||||
MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
|
MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
|
||||||
|
|
||||||
|
static const char *never_happen = "This should never happen.";
|
||||||
|
static const char *report_this =
|
||||||
|
"Please report this to the abituguru3 maintainer (see MAINTAINERS)";
|
||||||
|
|
||||||
/* wait while the uguru is busy (usually after a write) */
|
/* wait while the uguru is busy (usually after a write) */
|
||||||
static int abituguru3_wait_while_busy(struct abituguru3_data *data)
|
static int abituguru3_wait_while_busy(struct abituguru3_data *data)
|
||||||
|
@ -940,15 +946,13 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
|
||||||
if (abituguru3_motherboards[i].id == id)
|
if (abituguru3_motherboards[i].id == id)
|
||||||
break;
|
break;
|
||||||
if (!abituguru3_motherboards[i].id) {
|
if (!abituguru3_motherboards[i].id) {
|
||||||
printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard "
|
pr_err("error unknown motherboard ID: %04X. %s\n",
|
||||||
"ID: %04X. Please report this to the abituguru3 "
|
(unsigned int)id, report_this);
|
||||||
"maintainer (see MAINTAINERS)\n", (unsigned int)id);
|
|
||||||
goto abituguru3_probe_error;
|
goto abituguru3_probe_error;
|
||||||
}
|
}
|
||||||
data->sensors = abituguru3_motherboards[i].sensors;
|
data->sensors = abituguru3_motherboards[i].sensors;
|
||||||
|
|
||||||
printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
|
pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id);
|
||||||
"ID: %04X\n", (unsigned int)id);
|
|
||||||
|
|
||||||
/* Fill the sysfs attr array */
|
/* Fill the sysfs attr array */
|
||||||
sysfs_attr_i = 0;
|
sysfs_attr_i = 0;
|
||||||
|
@ -957,11 +961,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
|
||||||
for (i = 0; data->sensors[i].name; i++) {
|
for (i = 0; data->sensors[i].name; i++) {
|
||||||
/* Fail safe check, this should never happen! */
|
/* Fail safe check, this should never happen! */
|
||||||
if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
|
if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
|
||||||
printk(KERN_ERR ABIT_UGURU3_NAME
|
pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n",
|
||||||
": Fatal error motherboard has more sensors "
|
never_happen, report_this);
|
||||||
"then ABIT_UGURU3_MAX_NO_SENSORS. This should "
|
|
||||||
"never happen please report to the abituguru3 "
|
|
||||||
"maintainer (see MAINTAINERS)\n");
|
|
||||||
res = -ENAMETOOLONG;
|
res = -ENAMETOOLONG;
|
||||||
goto abituguru3_probe_error;
|
goto abituguru3_probe_error;
|
||||||
}
|
}
|
||||||
|
@ -983,10 +984,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
/* Fail safe check, this should never happen! */
|
/* Fail safe check, this should never happen! */
|
||||||
if (sysfs_names_free < 0) {
|
if (sysfs_names_free < 0) {
|
||||||
printk(KERN_ERR ABIT_UGURU3_NAME
|
pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n",
|
||||||
": Fatal error ran out of space for sysfs attr names. "
|
never_happen, report_this);
|
||||||
"This should never happen please report to the "
|
|
||||||
"abituguru3 maintainer (see MAINTAINERS)\n");
|
|
||||||
res = -ENAMETOOLONG;
|
res = -ENAMETOOLONG;
|
||||||
goto abituguru3_probe_error;
|
goto abituguru3_probe_error;
|
||||||
}
|
}
|
||||||
|
@ -1189,8 +1188,7 @@ static int __init abituguru3_detect(void)
|
||||||
"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
|
"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
|
||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
|
pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n");
|
||||||
"present because of \"force\" parameter\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,10 +1217,8 @@ static int __init abituguru3_init(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
#ifdef CONFIG_DMI
|
#ifdef CONFIG_DMI
|
||||||
printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
|
pr_warn("this motherboard was not detected using DMI. "
|
||||||
"not detected using DMI. Please send the output of "
|
"Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n");
|
||||||
"\"dmidecode\" to the abituguru3 maintainer "
|
|
||||||
"(see MAINTAINERS)\n");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1233,8 +1229,7 @@ static int __init abituguru3_init(void)
|
||||||
abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
|
abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
|
||||||
ABIT_UGURU3_BASE);
|
ABIT_UGURU3_BASE);
|
||||||
if (!abituguru3_pdev) {
|
if (!abituguru3_pdev) {
|
||||||
printk(KERN_ERR ABIT_UGURU3_NAME
|
pr_err("Device allocation failed\n");
|
||||||
": Device allocation failed\n");
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto exit_driver_unregister;
|
goto exit_driver_unregister;
|
||||||
}
|
}
|
||||||
|
@ -1245,15 +1240,13 @@ static int __init abituguru3_init(void)
|
||||||
|
|
||||||
err = platform_device_add_resources(abituguru3_pdev, &res, 1);
|
err = platform_device_add_resources(abituguru3_pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR ABIT_UGURU3_NAME
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
": Device resource addition failed (%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(abituguru3_pdev);
|
err = platform_device_add(abituguru3_pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR ABIT_UGURU3_NAME
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
": Device addition failed (%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
@ -274,7 +276,7 @@ static int adt7470_read_temperatures(struct i2c_client *client,
|
||||||
i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
|
i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
printk(KERN_ERR "ha ha, interrupted");
|
pr_err("ha ha, interrupted\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -36,6 +36,8 @@
|
||||||
asb100 7 3 1 4 0x31 0x0694 yes no
|
asb100 7 3 1 4 0x31 0x0694 yes no
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
@ -701,8 +703,7 @@ static int asb100_detect(struct i2c_client *client,
|
||||||
int val1, val2;
|
int val1, val2;
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||||
pr_debug("asb100.o: detect failed, "
|
pr_debug("detect failed, smbus byte data not supported!\n");
|
||||||
"smbus byte data not supported!\n");
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,7 +716,7 @@ static int asb100_detect(struct i2c_client *client,
|
||||||
(((!(val1 & 0x80)) && (val2 != 0x94)) ||
|
(((!(val1 & 0x80)) && (val2 != 0x94)) ||
|
||||||
/* Check for ASB100 ID (high byte ) */
|
/* Check for ASB100 ID (high byte ) */
|
||||||
((val1 & 0x80) && (val2 != 0x06)))) {
|
((val1 & 0x80) && (val2 != 0x06)))) {
|
||||||
pr_debug("asb100: detect failed, bad chip id 0x%02x!\n", val2);
|
pr_debug("detect failed, bad chip id 0x%02x!\n", val2);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,7 +745,7 @@ static int asb100_probe(struct i2c_client *client,
|
||||||
|
|
||||||
data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL);
|
data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
pr_debug("asb100.o: probe failed, kzalloc failed!\n");
|
pr_debug("probe failed, kzalloc failed!\n");
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto ERROR0;
|
goto ERROR0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* See COPYING in the top level directory of the kernel tree.
|
* See COPYING in the top level directory of the kernel tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
|
@ -1414,14 +1416,13 @@ static int __init atk0110_init(void)
|
||||||
|
|
||||||
/* Make sure it's safe to access the device through ACPI */
|
/* Make sure it's safe to access the device through ACPI */
|
||||||
if (!acpi_resources_are_enforced()) {
|
if (!acpi_resources_are_enforced()) {
|
||||||
pr_err("atk: Resources not safely usable due to "
|
pr_err("Resources not safely usable due to acpi_enforce_resources kernel parameter\n");
|
||||||
"acpi_enforce_resources kernel parameter\n");
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = acpi_bus_register_driver(&atk_driver);
|
ret = acpi_bus_register_driver(&atk_driver);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_info("atk: acpi_bus_register_driver failed: %d\n", ret);
|
pr_info("acpi_bus_register_driver failed: %d\n", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
* 02110-1301 USA.
|
* 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -445,8 +447,8 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
|
||||||
* without thermal sensors will be filtered out.
|
* without thermal sensors will be filtered out.
|
||||||
*/
|
*/
|
||||||
if (!cpu_has(c, X86_FEATURE_DTS)) {
|
if (!cpu_has(c, X86_FEATURE_DTS)) {
|
||||||
printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
|
pr_info("CPU (model=0x%x) has no thermal sensor\n",
|
||||||
" has no thermal sensor.\n", c->x86_model);
|
c->x86_model);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +468,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
|
||||||
pdev = platform_device_alloc(DRVNAME, cpu);
|
pdev = platform_device_alloc(DRVNAME, cpu);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,8 +480,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_free;
|
goto exit_device_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -2446,7 +2448,7 @@ static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr)
|
||||||
/* Get the base address of the runtime registers */
|
/* Get the base address of the runtime registers */
|
||||||
if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
|
if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
|
||||||
dme1737_sio_inb(sio_cip, 0x61))) {
|
dme1737_sio_inb(sio_cip, 0x61))) {
|
||||||
printk(KERN_ERR "dme1737: Base address not set.\n");
|
pr_err("Base address not set\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -2475,20 +2477,18 @@ static int __init dme1737_isa_device_add(unsigned short addr)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (!(pdev = platform_device_alloc("dme1737", addr))) {
|
if (!(pdev = platform_device_alloc("dme1737", addr))) {
|
||||||
printk(KERN_ERR "dme1737: Failed to allocate device.\n");
|
pr_err("Failed to allocate device\n");
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = platform_device_add_resources(pdev, &res, 1))) {
|
if ((err = platform_device_add_resources(pdev, &res, 1))) {
|
||||||
printk(KERN_ERR "dme1737: Failed to add device resource "
|
pr_err("Failed to add device resource (err = %d)\n", err);
|
||||||
"(err = %d).\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = platform_device_add(pdev))) {
|
if ((err = platform_device_add(pdev))) {
|
||||||
printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n",
|
pr_err("Failed to add device (err = %d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
337
drivers/hwmon/ds620.c
Normal file
337
drivers/hwmon/ds620.c
Normal file
|
@ -0,0 +1,337 @@
|
||||||
|
/*
|
||||||
|
* ds620.c - Support for temperature sensor and thermostat DS620
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
|
||||||
|
*
|
||||||
|
* based on ds1621.c by Christian W. Zuckschwerdt <zany@triq.net>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/hwmon.h>
|
||||||
|
#include <linux/hwmon-sysfs.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/sysfs.h>
|
||||||
|
#include <linux/i2c/ds620.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Many DS620 constants specified below
|
||||||
|
* 15 14 13 12 11 10 09 08
|
||||||
|
* |Done|NVB |THF |TLF |R1 |R0 |AUTOC|1SHOT|
|
||||||
|
*
|
||||||
|
* 07 06 05 04 03 02 01 00
|
||||||
|
* |PO2 |PO1 |A2 |A1 |A0 | | | |
|
||||||
|
*/
|
||||||
|
#define DS620_REG_CONFIG_DONE 0x8000
|
||||||
|
#define DS620_REG_CONFIG_NVB 0x4000
|
||||||
|
#define DS620_REG_CONFIG_THF 0x2000
|
||||||
|
#define DS620_REG_CONFIG_TLF 0x1000
|
||||||
|
#define DS620_REG_CONFIG_R1 0x0800
|
||||||
|
#define DS620_REG_CONFIG_R0 0x0400
|
||||||
|
#define DS620_REG_CONFIG_AUTOC 0x0200
|
||||||
|
#define DS620_REG_CONFIG_1SHOT 0x0100
|
||||||
|
#define DS620_REG_CONFIG_PO2 0x0080
|
||||||
|
#define DS620_REG_CONFIG_PO1 0x0040
|
||||||
|
#define DS620_REG_CONFIG_A2 0x0020
|
||||||
|
#define DS620_REG_CONFIG_A1 0x0010
|
||||||
|
#define DS620_REG_CONFIG_A0 0x0008
|
||||||
|
|
||||||
|
/* The DS620 registers */
|
||||||
|
static const u8 DS620_REG_TEMP[3] = {
|
||||||
|
0xAA, /* input, word, RO */
|
||||||
|
0xA2, /* min, word, RW */
|
||||||
|
0xA0, /* max, word, RW */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DS620_REG_CONF 0xAC /* word, RW */
|
||||||
|
#define DS620_COM_START 0x51 /* no data */
|
||||||
|
#define DS620_COM_STOP 0x22 /* no data */
|
||||||
|
|
||||||
|
/* Each client has this additional data */
|
||||||
|
struct ds620_data {
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
struct mutex update_lock;
|
||||||
|
char valid; /* !=0 if following fields are valid */
|
||||||
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
|
||||||
|
u16 temp[3]; /* Register values, word */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Temperature registers are word-sized.
|
||||||
|
* DS620 uses a high-byte first convention, which is exactly opposite to
|
||||||
|
* the SMBus standard.
|
||||||
|
*/
|
||||||
|
static int ds620_read_temp(struct i2c_client *client, u8 reg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_word_data(client, reg);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return swab16(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds620_write_temp(struct i2c_client *client, u8 reg, u16 value)
|
||||||
|
{
|
||||||
|
return i2c_smbus_write_word_data(client, reg, swab16(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds620_init_client(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct ds620_platform_data *ds620_info = client->dev.platform_data;
|
||||||
|
u16 conf, new_conf;
|
||||||
|
|
||||||
|
new_conf = conf =
|
||||||
|
swab16(i2c_smbus_read_word_data(client, DS620_REG_CONF));
|
||||||
|
|
||||||
|
/* switch to continuous conversion mode */
|
||||||
|
new_conf &= ~DS620_REG_CONFIG_1SHOT;
|
||||||
|
/* already high at power-on, but don't trust the BIOS! */
|
||||||
|
new_conf |= DS620_REG_CONFIG_PO2;
|
||||||
|
/* thermostat mode according to platform data */
|
||||||
|
if (ds620_info && ds620_info->pomode == 1)
|
||||||
|
new_conf &= ~DS620_REG_CONFIG_PO1; /* PO_LOW */
|
||||||
|
else if (ds620_info && ds620_info->pomode == 2)
|
||||||
|
new_conf |= DS620_REG_CONFIG_PO1; /* PO_HIGH */
|
||||||
|
else
|
||||||
|
new_conf &= ~DS620_REG_CONFIG_PO2; /* always low */
|
||||||
|
/* with highest precision */
|
||||||
|
new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0;
|
||||||
|
|
||||||
|
if (conf != new_conf)
|
||||||
|
i2c_smbus_write_word_data(client, DS620_REG_CONF,
|
||||||
|
swab16(new_conf));
|
||||||
|
|
||||||
|
/* start conversion */
|
||||||
|
i2c_smbus_write_byte(client, DS620_COM_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ds620_data *ds620_update_client(struct device *dev)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct ds620_data *data = i2c_get_clientdata(client);
|
||||||
|
struct ds620_data *ret = data;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|
||||||
|
|| !data->valid) {
|
||||||
|
int i;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
dev_dbg(&client->dev, "Starting ds620 update\n");
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
|
||||||
|
res = ds620_read_temp(client,
|
||||||
|
DS620_REG_TEMP[i]);
|
||||||
|
if (res < 0) {
|
||||||
|
ret = ERR_PTR(res);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->temp[i] = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->last_updated = jiffies;
|
||||||
|
data->valid = 1;
|
||||||
|
}
|
||||||
|
abort:
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_temp(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct ds620_data *data = ds620_update_client(dev);
|
||||||
|
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", ((data->temp[attr->index] / 8) * 625) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
long val;
|
||||||
|
|
||||||
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct ds620_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
res = strict_strtol(buf, 10, &val);
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
val = (val * 10 / 625) * 8;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
data->temp[attr->index] = val;
|
||||||
|
ds620_write_temp(client, DS620_REG_TEMP[attr->index],
|
||||||
|
data->temp[attr->index]);
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct ds620_data *data = ds620_update_client(dev);
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
u16 conf, new_conf;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
|
|
||||||
|
/* reset alarms if necessary */
|
||||||
|
res = i2c_smbus_read_word_data(client, DS620_REG_CONF);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
conf = swab16(res);
|
||||||
|
new_conf = conf;
|
||||||
|
new_conf &= ~attr->index;
|
||||||
|
if (conf != new_conf) {
|
||||||
|
res = i2c_smbus_write_word_data(client, DS620_REG_CONF,
|
||||||
|
swab16(new_conf));
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", !!(conf & attr->index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL,
|
||||||
|
DS620_REG_CONFIG_TLF);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
|
||||||
|
DS620_REG_CONFIG_THF);
|
||||||
|
|
||||||
|
static struct attribute *ds620_attributes[] = {
|
||||||
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group ds620_group = {
|
||||||
|
.attrs = ds620_attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ds620_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct ds620_data *data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
data = kzalloc(sizeof(struct ds620_data), GFP_KERNEL);
|
||||||
|
if (!data) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, data);
|
||||||
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
|
/* Initialize the DS620 chip */
|
||||||
|
ds620_init_client(client);
|
||||||
|
|
||||||
|
/* Register sysfs hooks */
|
||||||
|
err = sysfs_create_group(&client->dev.kobj, &ds620_group);
|
||||||
|
if (err)
|
||||||
|
goto exit_free;
|
||||||
|
|
||||||
|
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||||
|
if (IS_ERR(data->hwmon_dev)) {
|
||||||
|
err = PTR_ERR(data->hwmon_dev);
|
||||||
|
goto exit_remove_files;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(&client->dev, "temperature sensor found\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_remove_files:
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &ds620_group);
|
||||||
|
exit_free:
|
||||||
|
kfree(data);
|
||||||
|
exit:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds620_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct ds620_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
hwmon_device_unregister(data->hwmon_dev);
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &ds620_group);
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id ds620_id[] = {
|
||||||
|
{"ds620", 0},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(i2c, ds620_id);
|
||||||
|
|
||||||
|
/* This is the driver that will be inserted */
|
||||||
|
static struct i2c_driver ds620_driver = {
|
||||||
|
.class = I2C_CLASS_HWMON,
|
||||||
|
.driver = {
|
||||||
|
.name = "ds620",
|
||||||
|
},
|
||||||
|
.probe = ds620_probe,
|
||||||
|
.remove = ds620_remove,
|
||||||
|
.id_table = ds620_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init ds620_init(void)
|
||||||
|
{
|
||||||
|
return i2c_add_driver(&ds620_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit ds620_exit(void)
|
||||||
|
{
|
||||||
|
i2c_del_driver(&ds620_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
|
||||||
|
MODULE_DESCRIPTION("DS620 driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
module_init(ds620_init);
|
||||||
|
module_exit(ds620_exit);
|
|
@ -28,6 +28,8 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -1309,7 +1311,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
|
if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Out of memory\n");
|
pr_err("Out of memory\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,7 +1453,7 @@ static int __init f71805f_device_add(unsigned short address,
|
||||||
pdev = platform_device_alloc(DRVNAME, address);
|
pdev = platform_device_alloc(DRVNAME, address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1462,22 +1464,20 @@ static int __init f71805f_device_add(unsigned short address,
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_data(pdev, sio_data,
|
err = platform_device_add_data(pdev, sio_data,
|
||||||
sizeof(struct f71805f_sio_data));
|
sizeof(struct f71805f_sio_data));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
|
pr_err("Platform data allocation failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1516,28 +1516,25 @@ static int __init f71805f_find(int sioaddr, unsigned short *address,
|
||||||
sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
|
sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
|
pr_info("Unsupported Fintek device, skipping\n");
|
||||||
"skipping\n");
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
superio_select(sioaddr, F71805F_LD_HWM);
|
superio_select(sioaddr, F71805F_LD_HWM);
|
||||||
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
|
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
|
||||||
printk(KERN_WARNING DRVNAME ": Device not activated, "
|
pr_warn("Device not activated, skipping\n");
|
||||||
"skipping\n");
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
*address = superio_inw(sioaddr, SIO_REG_ADDR);
|
*address = superio_inw(sioaddr, SIO_REG_ADDR);
|
||||||
if (*address == 0) {
|
if (*address == 0) {
|
||||||
printk(KERN_WARNING DRVNAME ": Base address not set, "
|
pr_warn("Base address not set, skipping\n");
|
||||||
"skipping\n");
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
|
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
|
pr_info("Found %s chip at %#x, revision %u\n",
|
||||||
names[sio_data->kind], *address,
|
names[sio_data->kind], *address,
|
||||||
superio_inb(sioaddr, SIO_REG_DEVREV));
|
superio_inb(sioaddr, SIO_REG_DEVREV));
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -865,8 +867,7 @@ static inline int superio_enter(int base)
|
||||||
{
|
{
|
||||||
/* Don't step on other drivers' I/O space by accident */
|
/* Don't step on other drivers' I/O space by accident */
|
||||||
if (!request_muxed_region(base, 2, DRVNAME)) {
|
if (!request_muxed_region(base, 2, DRVNAME)) {
|
||||||
printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
|
pr_err("I/O address 0x%04x already in use\n", base);
|
||||||
base);
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2192,7 +2193,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
|
||||||
|
|
||||||
devid = superio_inw(sioaddr, SIO_REG_MANID);
|
devid = superio_inw(sioaddr, SIO_REG_MANID);
|
||||||
if (devid != SIO_FINTEK_ID) {
|
if (devid != SIO_FINTEK_ID) {
|
||||||
pr_debug(DRVNAME ": Not a Fintek device\n");
|
pr_debug("Not a Fintek device\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -2215,7 +2216,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
|
||||||
sio_data->type = f8000;
|
sio_data->type = f8000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
|
pr_info("Unsupported Fintek device: %04x\n",
|
||||||
(unsigned int)devid);
|
(unsigned int)devid);
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -2227,21 +2228,21 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
|
||||||
superio_select(sioaddr, SIO_F71882FG_LD_HWM);
|
superio_select(sioaddr, SIO_F71882FG_LD_HWM);
|
||||||
|
|
||||||
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
|
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
|
||||||
printk(KERN_WARNING DRVNAME ": Device not activated\n");
|
pr_warn("Device not activated\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
*address = superio_inw(sioaddr, SIO_REG_ADDR);
|
*address = superio_inw(sioaddr, SIO_REG_ADDR);
|
||||||
if (*address == 0) {
|
if (*address == 0) {
|
||||||
printk(KERN_WARNING DRVNAME ": Base address not set\n");
|
pr_warn("Base address not set\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
|
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n",
|
pr_info("Found %s chip at %#x, revision %d\n",
|
||||||
f71882fg_names[sio_data->type], (unsigned int)*address,
|
f71882fg_names[sio_data->type], (unsigned int)*address,
|
||||||
(int)superio_inb(sioaddr, SIO_REG_DEVREV));
|
(int)superio_inb(sioaddr, SIO_REG_DEVREV));
|
||||||
exit:
|
exit:
|
||||||
|
@ -2270,20 +2271,20 @@ static int __init f71882fg_device_add(unsigned short address,
|
||||||
|
|
||||||
err = platform_device_add_resources(f71882fg_pdev, &res, 1);
|
err = platform_device_add_resources(f71882fg_pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
|
pr_err("Device resource addition failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_data(f71882fg_pdev, sio_data,
|
err = platform_device_add_data(f71882fg_pdev, sio_data,
|
||||||
sizeof(struct f71882fg_sio_data));
|
sizeof(struct f71882fg_sio_data));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
|
pr_err("Platform data allocation failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(f71882fg_pdev);
|
err = platform_device_add(f71882fg_pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed\n");
|
pr_err("Device addition failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
|
@ -147,7 +149,7 @@ int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
|
||||||
static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
|
static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
|
||||||
{
|
{
|
||||||
lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
|
lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
|
||||||
printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
|
pr_info("hardware type %s found\n", dmi->ident);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -303,11 +305,10 @@ static int lis3lv02d_add(struct acpi_device *device)
|
||||||
|
|
||||||
/* If possible use a "standard" axes order */
|
/* If possible use a "standard" axes order */
|
||||||
if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
|
if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
|
||||||
printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n",
|
pr_info("Using custom axes %d,%d,%d\n",
|
||||||
lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
|
lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
|
||||||
} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
|
} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
|
||||||
printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
|
pr_info("laptop model unknown, using default axes configuration\n");
|
||||||
"using default axes configuration\n");
|
|
||||||
lis3_dev.ac = lis3lv02d_axis_normal;
|
lis3_dev.ac = lis3lv02d_axis_normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +386,7 @@ static int __init lis3lv02d_init_module(void)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
|
pr_info("driver loaded\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/hwmon-vid.h>
|
#include <linux/hwmon-vid.h>
|
||||||
|
@ -146,8 +148,8 @@ int vid_from_reg(int val, u8 vrm)
|
||||||
return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
|
return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
|
||||||
default: /* report 0 for unknown */
|
default: /* report 0 for unknown */
|
||||||
if (vrm)
|
if (vrm)
|
||||||
printk(KERN_WARNING "hwmon-vid: Requested unsupported "
|
pr_warn("Requested unsupported VRM version (%u)\n",
|
||||||
"VRM version (%u)\n", (unsigned int)vrm);
|
(unsigned int)vrm);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,8 +248,7 @@ u8 vid_which_vrm(void)
|
||||||
}
|
}
|
||||||
vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
|
vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
|
||||||
if (vrm_ret == 0)
|
if (vrm_ret == 0)
|
||||||
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
|
pr_info("Unknown VRM version of your x86 CPU\n");
|
||||||
"x86 CPU\n");
|
|
||||||
return vrm_ret;
|
return vrm_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +256,7 @@ u8 vid_which_vrm(void)
|
||||||
#else
|
#else
|
||||||
u8 vid_which_vrm(void)
|
u8 vid_which_vrm(void)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
|
pr_info("Unknown VRM version of your CPU\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
the Free Software Foundation; version 2 of the License.
|
the Free Software Foundation; version 2 of the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
@ -119,7 +121,7 @@ static int __init hwmon_init(void)
|
||||||
|
|
||||||
hwmon_class = class_create(THIS_MODULE, "hwmon");
|
hwmon_class = class_create(THIS_MODULE, "hwmon");
|
||||||
if (IS_ERR(hwmon_class)) {
|
if (IS_ERR(hwmon_class)) {
|
||||||
printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
|
pr_err("couldn't create sysfs class\n");
|
||||||
return PTR_ERR(hwmon_class);
|
return PTR_ERR(hwmon_class);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/ipmi.h>
|
#include <linux/ipmi.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
|
@ -1090,7 +1092,7 @@ static int __init aem_init(void)
|
||||||
|
|
||||||
res = driver_register(&aem_driver.driver);
|
res = driver_register(&aem_driver.driver);
|
||||||
if (res) {
|
if (res) {
|
||||||
printk(KERN_ERR "Can't register aem driver\n");
|
pr_err("Can't register aem driver\n");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
|
@ -860,8 +862,7 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
|
||||||
(p->irq_flags2 & IRQF_TRIGGER_MASK),
|
(p->irq_flags2 & IRQF_TRIGGER_MASK),
|
||||||
DRIVER_NAME, &lis3_dev);
|
DRIVER_NAME, &lis3_dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
printk(KERN_ERR DRIVER_NAME
|
pr_err("No second IRQ. Limited functionality\n");
|
||||||
"No second IRQ. Limited functionality\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +880,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
|
|
||||||
switch (dev->whoami) {
|
switch (dev->whoami) {
|
||||||
case WAI_12B:
|
case WAI_12B:
|
||||||
printk(KERN_INFO DRIVER_NAME ": 12 bits sensor found\n");
|
pr_info("12 bits sensor found\n");
|
||||||
dev->read_data = lis3lv02d_read_12;
|
dev->read_data = lis3lv02d_read_12;
|
||||||
dev->mdps_max_val = 2048;
|
dev->mdps_max_val = 2048;
|
||||||
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
|
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
|
||||||
|
@ -890,7 +891,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
|
dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
|
||||||
break;
|
break;
|
||||||
case WAI_8B:
|
case WAI_8B:
|
||||||
printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
|
pr_info("8 bits sensor found\n");
|
||||||
dev->read_data = lis3lv02d_read_8;
|
dev->read_data = lis3lv02d_read_8;
|
||||||
dev->mdps_max_val = 128;
|
dev->mdps_max_val = 128;
|
||||||
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
|
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
|
||||||
|
@ -901,7 +902,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
|
dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
|
||||||
break;
|
break;
|
||||||
case WAI_3DC:
|
case WAI_3DC:
|
||||||
printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
|
pr_info("8 bits 3DC sensor found\n");
|
||||||
dev->read_data = lis3lv02d_read_8;
|
dev->read_data = lis3lv02d_read_8;
|
||||||
dev->mdps_max_val = 128;
|
dev->mdps_max_val = 128;
|
||||||
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
|
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
|
||||||
|
@ -910,8 +911,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
dev->scale = LIS3_SENSITIVITY_8B;
|
dev->scale = LIS3_SENSITIVITY_8B;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR DRIVER_NAME
|
pr_err("unknown sensor type 0x%X\n", dev->whoami);
|
||||||
": unknown sensor type 0x%X\n", dev->whoami);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,7 +935,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lis3lv02d_joystick_enable())
|
if (lis3lv02d_joystick_enable())
|
||||||
printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
|
pr_err("joystick initialization failed\n");
|
||||||
|
|
||||||
/* passing in platform specific data is purely optional and only
|
/* passing in platform specific data is purely optional and only
|
||||||
* used by the SPI transport layer at the moment */
|
* used by the SPI transport layer at the moment */
|
||||||
|
@ -957,8 +957,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
|
|
||||||
/* bail if we did not get an IRQ from the bus layer */
|
/* bail if we did not get an IRQ from the bus layer */
|
||||||
if (!dev->irq) {
|
if (!dev->irq) {
|
||||||
printk(KERN_ERR DRIVER_NAME
|
pr_err("No IRQ. Disabling /dev/freefall\n");
|
||||||
": No IRQ. Disabling /dev/freefall\n");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,12 +984,12 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
|
||||||
DRIVER_NAME, &lis3_dev);
|
DRIVER_NAME, &lis3_dev);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n");
|
pr_err("Cannot get IRQ\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (misc_register(&lis3lv02d_misc_device))
|
if (misc_register(&lis3lv02d_misc_device))
|
||||||
printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
|
pr_err("misc_register failed\n");
|
||||||
out:
|
out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
@ -67,8 +69,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
|
||||||
*/
|
*/
|
||||||
status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
|
status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
printk(KERN_WARNING
|
pr_warn("spi_write_then_read failed with status %d\n", status);
|
||||||
"spi_write_then_read failed with status %d\n", status);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
raw = (rxbuf[0] << 8) + rxbuf[1];
|
raw = (rxbuf[0] << 8) + rxbuf[1];
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* lm95241.c - Part of lm_sensors, Linux kernel modules for hardware
|
* Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
|
||||||
* monitoring
|
|
||||||
* Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com>
|
|
||||||
*
|
*
|
||||||
* Based on the max1619 driver. The LM95241 is a sensor chip made by National
|
* The LM95241 is a sensor chip made by National Semiconductors.
|
||||||
* Semiconductors.
|
* It reports up to three temperatures (its own plus up to two external ones).
|
||||||
* It reports up to three temperatures (its own plus up to
|
* Complete datasheet can be obtained from National's website at:
|
||||||
* two external ones). Complete datasheet can be
|
|
||||||
* obtained from National's website at:
|
|
||||||
* http://www.national.com/ds.cgi/LM/LM95241.pdf
|
* http://www.national.com/ds.cgi/LM/LM95241.pdf
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -36,6 +32,8 @@
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
|
|
||||||
|
#define DEVNAME "lm95241"
|
||||||
|
|
||||||
static const unsigned short normal_i2c[] = {
|
static const unsigned short normal_i2c[] = {
|
||||||
0x19, 0x2a, 0x2b, I2C_CLIENT_END };
|
0x19, 0x2a, 0x2b, I2C_CLIENT_END };
|
||||||
|
|
||||||
|
@ -79,13 +77,14 @@ static const unsigned short normal_i2c[] = {
|
||||||
#define MANUFACTURER_ID 0x01
|
#define MANUFACTURER_ID 0x01
|
||||||
#define DEFAULT_REVISION 0xA4
|
#define DEFAULT_REVISION 0xA4
|
||||||
|
|
||||||
/* Conversions and various macros */
|
static const u8 lm95241_reg_address[] = {
|
||||||
#define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \
|
LM95241_REG_R_LOCAL_TEMPH,
|
||||||
(val_h)) * 1000 + (val_l) * 1000 / 256)
|
LM95241_REG_R_LOCAL_TEMPL,
|
||||||
|
LM95241_REG_R_REMOTE1_TEMPH,
|
||||||
/* Functions declaration */
|
LM95241_REG_R_REMOTE1_TEMPL,
|
||||||
static void lm95241_init_client(struct i2c_client *client);
|
LM95241_REG_R_REMOTE2_TEMPH,
|
||||||
static struct lm95241_data *lm95241_update_device(struct device *dev);
|
LM95241_REG_R_REMOTE2_TEMPL
|
||||||
|
};
|
||||||
|
|
||||||
/* Client data (each client gets its own) */
|
/* Client data (each client gets its own) */
|
||||||
struct lm95241_data {
|
struct lm95241_data {
|
||||||
|
@ -94,33 +93,185 @@ struct lm95241_data {
|
||||||
unsigned long last_updated, interval; /* in jiffies */
|
unsigned long last_updated, interval; /* in jiffies */
|
||||||
char valid; /* zero until following fields are valid */
|
char valid; /* zero until following fields are valid */
|
||||||
/* registers values */
|
/* registers values */
|
||||||
u8 local_h, local_l; /* local */
|
u8 temp[ARRAY_SIZE(lm95241_reg_address)];
|
||||||
u8 remote1_h, remote1_l; /* remote1 */
|
|
||||||
u8 remote2_h, remote2_l; /* remote2 */
|
|
||||||
u8 config, model, trutherm;
|
u8 config, model, trutherm;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Sysfs stuff */
|
/* Conversions */
|
||||||
#define show_temp(value) \
|
static int TempFromReg(u8 val_h, u8 val_l)
|
||||||
static ssize_t show_##value(struct device *dev, \
|
{
|
||||||
struct device_attribute *attr, char *buf) \
|
if (val_h & 0x80)
|
||||||
{ \
|
return val_h - 0x100;
|
||||||
struct lm95241_data *data = lm95241_update_device(dev); \
|
return val_h * 1000 + val_l * 1000 / 256;
|
||||||
snprintf(buf, PAGE_SIZE - 1, "%d\n", \
|
}
|
||||||
TEMP_FROM_REG(data->value##_h, data->value##_l)); \
|
|
||||||
return strlen(buf); \
|
static struct lm95241_data *lm95241_update_device(struct device *dev)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (time_after(jiffies, data->last_updated + data->interval) ||
|
||||||
|
!data->valid) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev_dbg(&client->dev, "Updating lm95241 data.\n");
|
||||||
|
for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++)
|
||||||
|
data->temp[i]
|
||||||
|
= i2c_smbus_read_byte_data(client,
|
||||||
|
lm95241_reg_address[i]);
|
||||||
|
data->last_updated = jiffies;
|
||||||
|
data->valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sysfs stuff */
|
||||||
|
static ssize_t show_input(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct lm95241_data *data = lm95241_update_device(dev);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE - 1, "%d\n",
|
||||||
|
TempFromReg(data->temp[to_sensor_dev_attr(attr)->index],
|
||||||
|
data->temp[to_sensor_dev_attr(attr)->index + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_type(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE - 1,
|
||||||
|
data->model & to_sensor_dev_attr(attr)->index ? "1\n" : "2\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t set_type(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
unsigned long val;
|
||||||
|
int shift;
|
||||||
|
u8 mask = to_sensor_dev_attr(attr)->index;
|
||||||
|
|
||||||
|
if (strict_strtoul(buf, 10, &val) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (val != 1 && val != 2)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
shift = mask == R1MS_MASK ? TT1_SHIFT : TT2_SHIFT;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
data->trutherm &= ~(TT_MASK << shift);
|
||||||
|
if (val == 1) {
|
||||||
|
data->model |= mask;
|
||||||
|
data->trutherm |= (TT_ON << shift);
|
||||||
|
} else {
|
||||||
|
data->model &= ~mask;
|
||||||
|
data->trutherm |= (TT_OFF << shift);
|
||||||
|
}
|
||||||
|
data->valid = 0;
|
||||||
|
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
|
||||||
|
data->model);
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
|
||||||
|
data->trutherm);
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_min(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE - 1,
|
||||||
|
data->config & to_sensor_dev_attr(attr)->index ?
|
||||||
|
"-127000\n" : "0\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t set_min(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
long val;
|
||||||
|
|
||||||
|
if (strict_strtol(buf, 10, &val) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (val < -128000)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (val < 0)
|
||||||
|
data->config |= to_sensor_dev_attr(attr)->index;
|
||||||
|
else
|
||||||
|
data->config &= ~to_sensor_dev_attr(attr)->index;
|
||||||
|
data->valid = 0;
|
||||||
|
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_max(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE - 1,
|
||||||
|
data->config & to_sensor_dev_attr(attr)->index ?
|
||||||
|
"127000\n" : "255000\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t set_max(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
long val;
|
||||||
|
|
||||||
|
if (strict_strtol(buf, 10, &val) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (val >= 256000)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (val <= 127000)
|
||||||
|
data->config |= to_sensor_dev_attr(attr)->index;
|
||||||
|
else
|
||||||
|
data->config &= ~to_sensor_dev_attr(attr)->index;
|
||||||
|
data->valid = 0;
|
||||||
|
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
show_temp(local);
|
|
||||||
show_temp(remote1);
|
|
||||||
show_temp(remote2);
|
|
||||||
|
|
||||||
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
|
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct lm95241_data *data = lm95241_update_device(dev);
|
struct lm95241_data *data = lm95241_update_device(dev);
|
||||||
|
|
||||||
snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ);
|
return snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval
|
||||||
return strlen(buf);
|
/ HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
|
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
|
||||||
|
@ -138,176 +289,34 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define show_type(flag) \
|
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
|
||||||
static ssize_t show_type##flag(struct device *dev, \
|
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
|
||||||
struct device_attribute *attr, char *buf) \
|
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 4);
|
||||||
{ \
|
static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type,
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
R1MS_MASK);
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client); \
|
static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type,
|
||||||
\
|
R2MS_MASK);
|
||||||
snprintf(buf, PAGE_SIZE - 1, \
|
static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min,
|
||||||
data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \
|
R1DF_MASK);
|
||||||
return strlen(buf); \
|
static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min,
|
||||||
}
|
R2DF_MASK);
|
||||||
show_type(1);
|
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max,
|
||||||
show_type(2);
|
R1DF_MASK);
|
||||||
|
static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max,
|
||||||
#define show_min(flag) \
|
R2DF_MASK);
|
||||||
static ssize_t show_min##flag(struct device *dev, \
|
|
||||||
struct device_attribute *attr, char *buf) \
|
|
||||||
{ \
|
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client); \
|
|
||||||
\
|
|
||||||
snprintf(buf, PAGE_SIZE - 1, \
|
|
||||||
data->config & R##flag##DF_MASK ? \
|
|
||||||
"-127000\n" : "0\n"); \
|
|
||||||
return strlen(buf); \
|
|
||||||
}
|
|
||||||
show_min(1);
|
|
||||||
show_min(2);
|
|
||||||
|
|
||||||
#define show_max(flag) \
|
|
||||||
static ssize_t show_max##flag(struct device *dev, \
|
|
||||||
struct device_attribute *attr, char *buf) \
|
|
||||||
{ \
|
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client); \
|
|
||||||
\
|
|
||||||
snprintf(buf, PAGE_SIZE - 1, \
|
|
||||||
data->config & R##flag##DF_MASK ? \
|
|
||||||
"127000\n" : "255000\n"); \
|
|
||||||
return strlen(buf); \
|
|
||||||
}
|
|
||||||
show_max(1);
|
|
||||||
show_max(2);
|
|
||||||
|
|
||||||
#define set_type(flag) \
|
|
||||||
static ssize_t set_type##flag(struct device *dev, \
|
|
||||||
struct device_attribute *attr, \
|
|
||||||
const char *buf, size_t count) \
|
|
||||||
{ \
|
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client); \
|
|
||||||
\
|
|
||||||
long val; \
|
|
||||||
\
|
|
||||||
if (strict_strtol(buf, 10, &val) < 0) \
|
|
||||||
return -EINVAL; \
|
|
||||||
\
|
|
||||||
if ((val == 1) || (val == 2)) { \
|
|
||||||
\
|
|
||||||
mutex_lock(&data->update_lock); \
|
|
||||||
\
|
|
||||||
data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \
|
|
||||||
if (val == 1) { \
|
|
||||||
data->model |= R##flag##MS_MASK; \
|
|
||||||
data->trutherm |= (TT_ON << TT##flag##_SHIFT); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
data->model &= ~R##flag##MS_MASK; \
|
|
||||||
data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
data->valid = 0; \
|
|
||||||
\
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \
|
|
||||||
data->model); \
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \
|
|
||||||
data->trutherm); \
|
|
||||||
\
|
|
||||||
mutex_unlock(&data->update_lock); \
|
|
||||||
\
|
|
||||||
} \
|
|
||||||
return count; \
|
|
||||||
}
|
|
||||||
set_type(1);
|
|
||||||
set_type(2);
|
|
||||||
|
|
||||||
#define set_min(flag) \
|
|
||||||
static ssize_t set_min##flag(struct device *dev, \
|
|
||||||
struct device_attribute *devattr, const char *buf, size_t count) \
|
|
||||||
{ \
|
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client); \
|
|
||||||
\
|
|
||||||
long val; \
|
|
||||||
\
|
|
||||||
if (strict_strtol(buf, 10, &val) < 0) \
|
|
||||||
return -EINVAL;\
|
|
||||||
\
|
|
||||||
mutex_lock(&data->update_lock); \
|
|
||||||
\
|
|
||||||
if (val < 0) \
|
|
||||||
data->config |= R##flag##DF_MASK; \
|
|
||||||
else \
|
|
||||||
data->config &= ~R##flag##DF_MASK; \
|
|
||||||
\
|
|
||||||
data->valid = 0; \
|
|
||||||
\
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \
|
|
||||||
data->config); \
|
|
||||||
\
|
|
||||||
mutex_unlock(&data->update_lock); \
|
|
||||||
\
|
|
||||||
return count; \
|
|
||||||
}
|
|
||||||
set_min(1);
|
|
||||||
set_min(2);
|
|
||||||
|
|
||||||
#define set_max(flag) \
|
|
||||||
static ssize_t set_max##flag(struct device *dev, \
|
|
||||||
struct device_attribute *devattr, const char *buf, size_t count) \
|
|
||||||
{ \
|
|
||||||
struct i2c_client *client = to_i2c_client(dev); \
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client); \
|
|
||||||
\
|
|
||||||
long val; \
|
|
||||||
\
|
|
||||||
if (strict_strtol(buf, 10, &val) < 0) \
|
|
||||||
return -EINVAL; \
|
|
||||||
\
|
|
||||||
mutex_lock(&data->update_lock); \
|
|
||||||
\
|
|
||||||
if (val <= 127000) \
|
|
||||||
data->config |= R##flag##DF_MASK; \
|
|
||||||
else \
|
|
||||||
data->config &= ~R##flag##DF_MASK; \
|
|
||||||
\
|
|
||||||
data->valid = 0; \
|
|
||||||
\
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \
|
|
||||||
data->config); \
|
|
||||||
\
|
|
||||||
mutex_unlock(&data->update_lock); \
|
|
||||||
\
|
|
||||||
return count; \
|
|
||||||
}
|
|
||||||
set_max(1);
|
|
||||||
set_max(2);
|
|
||||||
|
|
||||||
static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL);
|
|
||||||
static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL);
|
|
||||||
static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL);
|
|
||||||
static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1);
|
|
||||||
static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2);
|
|
||||||
static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1);
|
|
||||||
static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2);
|
|
||||||
static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1);
|
|
||||||
static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2);
|
|
||||||
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
|
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
|
||||||
set_interval);
|
set_interval);
|
||||||
|
|
||||||
static struct attribute *lm95241_attributes[] = {
|
static struct attribute *lm95241_attributes[] = {
|
||||||
&dev_attr_temp1_input.attr,
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||||
&dev_attr_temp2_input.attr,
|
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||||
&dev_attr_temp3_input.attr,
|
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||||
&dev_attr_temp2_type.attr,
|
&sensor_dev_attr_temp2_type.dev_attr.attr,
|
||||||
&dev_attr_temp3_type.attr,
|
&sensor_dev_attr_temp3_type.dev_attr.attr,
|
||||||
&dev_attr_temp2_min.attr,
|
&sensor_dev_attr_temp2_min.dev_attr.attr,
|
||||||
&dev_attr_temp3_min.attr,
|
&sensor_dev_attr_temp3_min.dev_attr.attr,
|
||||||
&dev_attr_temp2_max.attr,
|
&sensor_dev_attr_temp2_max.dev_attr.attr,
|
||||||
&dev_attr_temp3_max.attr,
|
&sensor_dev_attr_temp3_max.dev_attr.attr,
|
||||||
&dev_attr_update_interval.attr,
|
&dev_attr_update_interval.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -331,7 +340,7 @@ static int lm95241_detect(struct i2c_client *new_client,
|
||||||
== MANUFACTURER_ID)
|
== MANUFACTURER_ID)
|
||||||
&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
|
&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
|
||||||
>= DEFAULT_REVISION)) {
|
>= DEFAULT_REVISION)) {
|
||||||
name = "lm95241";
|
name = DEVNAME;
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
|
dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
|
||||||
address);
|
address);
|
||||||
|
@ -343,6 +352,25 @@ static int lm95241_detect(struct i2c_client *new_client,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lm95241_init_client(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
data->interval = HZ; /* 1 sec default */
|
||||||
|
data->valid = 0;
|
||||||
|
data->config = CFG_CR0076;
|
||||||
|
data->model = 0;
|
||||||
|
data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
|
||||||
|
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER,
|
||||||
|
R1FE_MASK | R2FE_MASK);
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
|
||||||
|
data->trutherm);
|
||||||
|
i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
|
||||||
|
data->model);
|
||||||
|
}
|
||||||
|
|
||||||
static int lm95241_probe(struct i2c_client *new_client,
|
static int lm95241_probe(struct i2c_client *new_client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -382,26 +410,6 @@ exit:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lm95241_init_client(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
data->interval = HZ; /* 1 sec default */
|
|
||||||
data->valid = 0;
|
|
||||||
data->config = CFG_CR0076;
|
|
||||||
data->model = 0;
|
|
||||||
data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
|
|
||||||
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
|
|
||||||
data->config);
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER,
|
|
||||||
R1FE_MASK | R2FE_MASK);
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
|
|
||||||
data->trutherm);
|
|
||||||
i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
|
|
||||||
data->model);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lm95241_remove(struct i2c_client *client)
|
static int lm95241_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client);
|
struct lm95241_data *data = i2c_get_clientdata(client);
|
||||||
|
@ -413,46 +421,9 @@ static int lm95241_remove(struct i2c_client *client)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct lm95241_data *lm95241_update_device(struct device *dev)
|
|
||||||
{
|
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
|
||||||
struct lm95241_data *data = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + data->interval) ||
|
|
||||||
!data->valid) {
|
|
||||||
dev_dbg(&client->dev, "Updating lm95241 data.\n");
|
|
||||||
data->local_h =
|
|
||||||
i2c_smbus_read_byte_data(client,
|
|
||||||
LM95241_REG_R_LOCAL_TEMPH);
|
|
||||||
data->local_l =
|
|
||||||
i2c_smbus_read_byte_data(client,
|
|
||||||
LM95241_REG_R_LOCAL_TEMPL);
|
|
||||||
data->remote1_h =
|
|
||||||
i2c_smbus_read_byte_data(client,
|
|
||||||
LM95241_REG_R_REMOTE1_TEMPH);
|
|
||||||
data->remote1_l =
|
|
||||||
i2c_smbus_read_byte_data(client,
|
|
||||||
LM95241_REG_R_REMOTE1_TEMPL);
|
|
||||||
data->remote2_h =
|
|
||||||
i2c_smbus_read_byte_data(client,
|
|
||||||
LM95241_REG_R_REMOTE2_TEMPH);
|
|
||||||
data->remote2_l =
|
|
||||||
i2c_smbus_read_byte_data(client,
|
|
||||||
LM95241_REG_R_REMOTE2_TEMPL);
|
|
||||||
data->last_updated = jiffies;
|
|
||||||
data->valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&data->update_lock);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Driver data (common to all clients) */
|
/* Driver data (common to all clients) */
|
||||||
static const struct i2c_device_id lm95241_id[] = {
|
static const struct i2c_device_id lm95241_id[] = {
|
||||||
{ "lm95241", 0 },
|
{ DEVNAME, 0 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, lm95241_id);
|
MODULE_DEVICE_TABLE(i2c, lm95241_id);
|
||||||
|
@ -460,7 +431,7 @@ MODULE_DEVICE_TABLE(i2c, lm95241_id);
|
||||||
static struct i2c_driver lm95241_driver = {
|
static struct i2c_driver lm95241_driver = {
|
||||||
.class = I2C_CLASS_HWMON,
|
.class = I2C_CLASS_HWMON,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "lm95241",
|
.name = DEVNAME,
|
||||||
},
|
},
|
||||||
.probe = lm95241_probe,
|
.probe = lm95241_probe,
|
||||||
.remove = lm95241_remove,
|
.remove = lm95241_remove,
|
||||||
|
@ -479,7 +450,7 @@ static void __exit sensors_lm95241_exit(void)
|
||||||
i2c_del_driver(&lm95241_driver);
|
i2c_del_driver(&lm95241_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>");
|
MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
|
||||||
MODULE_DESCRIPTION("LM95241 sensor driver");
|
MODULE_DESCRIPTION("LM95241 sensor driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -290,8 +292,7 @@ static struct i2c_driver pcf8591_driver = {
|
||||||
static int __init pcf8591_init(void)
|
static int __init pcf8591_init(void)
|
||||||
{
|
{
|
||||||
if (input_mode < 0 || input_mode > 3) {
|
if (input_mode < 0 || input_mode > 3) {
|
||||||
printk(KERN_WARNING "pcf8591: invalid input_mode (%d)\n",
|
pr_warn("invalid input_mode (%d)\n", input_mode);
|
||||||
input_mode);
|
|
||||||
input_mode = 0;
|
input_mode = 0;
|
||||||
}
|
}
|
||||||
return i2c_add_driver(&pcf8591_driver);
|
return i2c_add_driver(&pcf8591_driver);
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
* 02110-1301 USA.
|
* 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -303,7 +305,7 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu)
|
||||||
pdev = platform_device_alloc(DRVNAME, cpu);
|
pdev = platform_device_alloc(DRVNAME, cpu);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,8 +317,7 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu)
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_free;
|
goto exit_device_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
307
drivers/hwmon/sht21.c
Normal file
307
drivers/hwmon/sht21.c
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
/* Sensirion SHT21 humidity and temperature sensor driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Urs Fleisch <urs.fleisch@sensirion.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Data sheet available (5/2010) at
|
||||||
|
* http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/hwmon.h>
|
||||||
|
#include <linux/hwmon-sysfs.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
|
||||||
|
/* I2C command bytes */
|
||||||
|
#define SHT21_TRIG_T_MEASUREMENT_HM 0xe3
|
||||||
|
#define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sht21 - SHT21 device specific data
|
||||||
|
* @hwmon_dev: device registered with hwmon
|
||||||
|
* @lock: mutex to protect measurement values
|
||||||
|
* @valid: only 0 before first measurement is taken
|
||||||
|
* @last_update: time of last update (jiffies)
|
||||||
|
* @temperature: cached temperature measurement value
|
||||||
|
* @humidity: cached humidity measurement value
|
||||||
|
*/
|
||||||
|
struct sht21 {
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
struct mutex lock;
|
||||||
|
char valid;
|
||||||
|
unsigned long last_update;
|
||||||
|
int temperature;
|
||||||
|
int humidity;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_temp_ticks_to_millicelsius() - convert raw temperature ticks to
|
||||||
|
* milli celsius
|
||||||
|
* @ticks: temperature ticks value received from sensor
|
||||||
|
*/
|
||||||
|
static inline int sht21_temp_ticks_to_millicelsius(int ticks)
|
||||||
|
{
|
||||||
|
ticks &= ~0x0003; /* clear status bits */
|
||||||
|
/*
|
||||||
|
* Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2,
|
||||||
|
* optimized for integer fixed point (3 digits) arithmetic
|
||||||
|
*/
|
||||||
|
return ((21965 * ticks) >> 13) - 46850;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_rh_ticks_to_per_cent_mille() - convert raw humidity ticks to
|
||||||
|
* one-thousandths of a percent relative humidity
|
||||||
|
* @ticks: humidity ticks value received from sensor
|
||||||
|
*/
|
||||||
|
static inline int sht21_rh_ticks_to_per_cent_mille(int ticks)
|
||||||
|
{
|
||||||
|
ticks &= ~0x0003; /* clear status bits */
|
||||||
|
/*
|
||||||
|
* Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1,
|
||||||
|
* optimized for integer fixed point (3 digits) arithmetic
|
||||||
|
*/
|
||||||
|
return ((15625 * ticks) >> 13) - 6000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_read_word_data() - read word from register
|
||||||
|
* @client: I2C client device
|
||||||
|
* @reg: I2C command byte
|
||||||
|
*
|
||||||
|
* Returns value, negative errno on error.
|
||||||
|
*/
|
||||||
|
static inline int sht21_read_word_data(struct i2c_client *client, u8 reg)
|
||||||
|
{
|
||||||
|
int ret = i2c_smbus_read_word_data(client, reg);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
/*
|
||||||
|
* SMBus specifies low byte first, but the SHT21 returns MSB
|
||||||
|
* first, so we have to swab16 the values
|
||||||
|
*/
|
||||||
|
return swab16(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_update_measurements() - get updated measurements from device
|
||||||
|
* @client: I2C client device
|
||||||
|
*
|
||||||
|
* Returns 0 on success, else negative errno.
|
||||||
|
*/
|
||||||
|
static int sht21_update_measurements(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct sht21 *sht21 = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
mutex_lock(&sht21->lock);
|
||||||
|
/*
|
||||||
|
* Data sheet 2.4:
|
||||||
|
* SHT2x should not be active for more than 10% of the time - e.g.
|
||||||
|
* maximum two measurements per second at 12bit accuracy shall be made.
|
||||||
|
*/
|
||||||
|
if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) {
|
||||||
|
ret = sht21_read_word_data(client, SHT21_TRIG_T_MEASUREMENT_HM);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
sht21->temperature = sht21_temp_ticks_to_millicelsius(ret);
|
||||||
|
ret = sht21_read_word_data(client,
|
||||||
|
SHT21_TRIG_RH_MEASUREMENT_HM);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret);
|
||||||
|
sht21->last_update = jiffies;
|
||||||
|
sht21->valid = 1;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
mutex_unlock(&sht21->lock);
|
||||||
|
|
||||||
|
return ret >= 0 ? 0 : ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_show_temperature() - show temperature measurement value in sysfs
|
||||||
|
* @dev: device
|
||||||
|
* @attr: device attribute
|
||||||
|
* @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to
|
||||||
|
*
|
||||||
|
* Will be called on read access to temp1_input sysfs attribute.
|
||||||
|
* Returns number of bytes written into buffer, negative errno on error.
|
||||||
|
*/
|
||||||
|
static ssize_t sht21_show_temperature(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct sht21 *sht21 = i2c_get_clientdata(client);
|
||||||
|
int ret = sht21_update_measurements(client);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return sprintf(buf, "%d\n", sht21->temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_show_humidity() - show humidity measurement value in sysfs
|
||||||
|
* @dev: device
|
||||||
|
* @attr: device attribute
|
||||||
|
* @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to
|
||||||
|
*
|
||||||
|
* Will be called on read access to humidity1_input sysfs attribute.
|
||||||
|
* Returns number of bytes written into buffer, negative errno on error.
|
||||||
|
*/
|
||||||
|
static ssize_t sht21_show_humidity(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct sht21 *sht21 = i2c_get_clientdata(client);
|
||||||
|
int ret = sht21_update_measurements(client);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return sprintf(buf, "%d\n", sht21->humidity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sysfs attributes */
|
||||||
|
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature,
|
||||||
|
NULL, 0);
|
||||||
|
static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity,
|
||||||
|
NULL, 0);
|
||||||
|
|
||||||
|
static struct attribute *sht21_attributes[] = {
|
||||||
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_humidity1_input.dev_attr.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group sht21_attr_group = {
|
||||||
|
.attrs = sht21_attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_probe() - probe device
|
||||||
|
* @client: I2C client device
|
||||||
|
* @id: device ID
|
||||||
|
*
|
||||||
|
* Called by the I2C core when an entry in the ID table matches a
|
||||||
|
* device's name.
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
static int __devinit sht21_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct sht21 *sht21;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(client->adapter,
|
||||||
|
I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"adapter does not support SMBus word transactions\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL);
|
||||||
|
if (!sht21) {
|
||||||
|
dev_dbg(&client->dev, "kzalloc failed\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
i2c_set_clientdata(client, sht21);
|
||||||
|
|
||||||
|
mutex_init(&sht21->lock);
|
||||||
|
|
||||||
|
err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group);
|
||||||
|
if (err) {
|
||||||
|
dev_dbg(&client->dev, "could not create sysfs files\n");
|
||||||
|
goto fail_free;
|
||||||
|
}
|
||||||
|
sht21->hwmon_dev = hwmon_device_register(&client->dev);
|
||||||
|
if (IS_ERR(sht21->hwmon_dev)) {
|
||||||
|
dev_dbg(&client->dev, "unable to register hwmon device\n");
|
||||||
|
err = PTR_ERR(sht21->hwmon_dev);
|
||||||
|
goto fail_remove_sysfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(&client->dev, "initialized\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_remove_sysfs:
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
|
||||||
|
fail_free:
|
||||||
|
kfree(sht21);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_remove() - remove device
|
||||||
|
* @client: I2C client device
|
||||||
|
*/
|
||||||
|
static int __devexit sht21_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct sht21 *sht21 = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
hwmon_device_unregister(sht21->hwmon_dev);
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
|
||||||
|
kfree(sht21);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device ID table */
|
||||||
|
static const struct i2c_device_id sht21_id[] = {
|
||||||
|
{ "sht21", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, sht21_id);
|
||||||
|
|
||||||
|
static struct i2c_driver sht21_driver = {
|
||||||
|
.driver.name = "sht21",
|
||||||
|
.probe = sht21_probe,
|
||||||
|
.remove = __devexit_p(sht21_remove),
|
||||||
|
.id_table = sht21_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_init() - initialize driver
|
||||||
|
*
|
||||||
|
* Called when kernel is booted or module is inserted.
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
static int __init sht21_init(void)
|
||||||
|
{
|
||||||
|
return i2c_add_driver(&sht21_driver);
|
||||||
|
}
|
||||||
|
module_init(sht21_init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sht21_init() - clean up driver
|
||||||
|
*
|
||||||
|
* Called when module is removed.
|
||||||
|
*/
|
||||||
|
static void __exit sht21_exit(void)
|
||||||
|
{
|
||||||
|
i2c_del_driver(&sht21_driver);
|
||||||
|
}
|
||||||
|
module_exit(sht21_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Urs Fleisch <urs.fleisch@sensirion.com>");
|
||||||
|
MODULE_DESCRIPTION("Sensirion SHT21 humidity and temperature sensor driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -50,6 +50,8 @@
|
||||||
735 0008 0735
|
735 0008 0735
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
@ -735,21 +737,19 @@ static int __devinit sis5595_device_add(unsigned short address)
|
||||||
pdev = platform_device_alloc("sis5595", address);
|
pdev = platform_device_alloc("sis5595", address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR "sis5595: Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "sis5595: Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "sis5595: Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
@ -311,21 +313,19 @@ static int __init smsc47b397_device_add(unsigned short address)
|
||||||
pdev = platform_device_alloc(DRVNAME, address);
|
pdev = platform_device_alloc(DRVNAME, address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,8 +367,7 @@ static int __init smsc47b397_find(unsigned short *addr)
|
||||||
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
|
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
|
||||||
| superio_inb(SUPERIO_REG_BASE_LSB);
|
| superio_inb(SUPERIO_REG_BASE_LSB);
|
||||||
|
|
||||||
printk(KERN_INFO DRVNAME ": found SMSC %s "
|
pr_info("found SMSC %s (base address 0x%04x, revision %u)\n",
|
||||||
"(base address 0x%04x, revision %u)\n",
|
|
||||||
name, *addr, rev);
|
name, *addr, rev);
|
||||||
|
|
||||||
superio_exit();
|
superio_exit();
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
@ -435,30 +437,29 @@ static int __init smsc47m1_find(unsigned short *addr,
|
||||||
*/
|
*/
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 0x51:
|
case 0x51:
|
||||||
pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
|
pr_info("Found SMSC LPC47B27x\n");
|
||||||
sio_data->type = smsc47m1;
|
sio_data->type = smsc47m1;
|
||||||
break;
|
break;
|
||||||
case 0x59:
|
case 0x59:
|
||||||
pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
|
pr_info("Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
|
||||||
sio_data->type = smsc47m1;
|
sio_data->type = smsc47m1;
|
||||||
break;
|
break;
|
||||||
case 0x5F:
|
case 0x5F:
|
||||||
pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
|
pr_info("Found SMSC LPC47M14x\n");
|
||||||
sio_data->type = smsc47m1;
|
sio_data->type = smsc47m1;
|
||||||
break;
|
break;
|
||||||
case 0x60:
|
case 0x60:
|
||||||
pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
|
pr_info("Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
|
||||||
sio_data->type = smsc47m1;
|
sio_data->type = smsc47m1;
|
||||||
break;
|
break;
|
||||||
case 0x6B:
|
case 0x6B:
|
||||||
if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
|
if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
|
||||||
pr_debug(DRVNAME ": "
|
pr_debug("Found SMSC LPC47M233, unsupported\n");
|
||||||
"Found SMSC LPC47M233, unsupported\n");
|
|
||||||
superio_exit();
|
superio_exit();
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_info(DRVNAME ": Found SMSC LPC47M292\n");
|
pr_info("Found SMSC LPC47M292\n");
|
||||||
sio_data->type = smsc47m2;
|
sio_data->type = smsc47m2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -470,7 +471,7 @@ static int __init smsc47m1_find(unsigned short *addr,
|
||||||
*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
|
*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
|
||||||
| superio_inb(SUPERIO_REG_BASE + 1);
|
| superio_inb(SUPERIO_REG_BASE + 1);
|
||||||
if (*addr == 0) {
|
if (*addr == 0) {
|
||||||
pr_info(DRVNAME ": Device address not set, will not use\n");
|
pr_info("Device address not set, will not use\n");
|
||||||
superio_exit();
|
superio_exit();
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -479,7 +480,7 @@ static int __init smsc47m1_find(unsigned short *addr,
|
||||||
* Compaq Presario S4000NX) */
|
* Compaq Presario S4000NX) */
|
||||||
sio_data->activate = superio_inb(SUPERIO_REG_ACT);
|
sio_data->activate = superio_inb(SUPERIO_REG_ACT);
|
||||||
if ((sio_data->activate & 0x01) == 0) {
|
if ((sio_data->activate & 0x01) == 0) {
|
||||||
pr_info(DRVNAME ": Enabling device\n");
|
pr_info("Enabling device\n");
|
||||||
superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01);
|
superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,7 +495,7 @@ static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
|
||||||
superio_enter();
|
superio_enter();
|
||||||
superio_select();
|
superio_select();
|
||||||
|
|
||||||
pr_info(DRVNAME ": Disabling device\n");
|
pr_info("Disabling device\n");
|
||||||
superio_outb(SUPERIO_REG_ACT, sio_data->activate);
|
superio_outb(SUPERIO_REG_ACT, sio_data->activate);
|
||||||
|
|
||||||
superio_exit();
|
superio_exit();
|
||||||
|
@ -823,28 +824,26 @@ static int __init smsc47m1_device_add(unsigned short address,
|
||||||
pdev = platform_device_alloc(DRVNAME, address);
|
pdev = platform_device_alloc(DRVNAME, address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_data(pdev, sio_data,
|
err = platform_device_add_data(pdev, sio_data,
|
||||||
sizeof(struct smsc47m1_sio_data));
|
sizeof(struct smsc47m1_sio_data));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
|
pr_err("Platform data allocation failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
* 02110-1301 USA.
|
* 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -202,7 +204,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu)
|
||||||
pdev = platform_device_alloc(DRVNAME, cpu);
|
pdev = platform_device_alloc(DRVNAME, cpu);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,8 +216,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu)
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_free;
|
goto exit_device_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,13 +238,16 @@ exit:
|
||||||
|
|
||||||
static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
|
static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct pdev_entry *p, *n;
|
struct pdev_entry *p;
|
||||||
|
|
||||||
mutex_lock(&pdev_list_mutex);
|
mutex_lock(&pdev_list_mutex);
|
||||||
list_for_each_entry_safe(p, n, &pdev_list, list) {
|
list_for_each_entry(p, &pdev_list, list) {
|
||||||
if (p->cpu == cpu) {
|
if (p->cpu == cpu) {
|
||||||
platform_device_unregister(p->pdev);
|
platform_device_unregister(p->pdev);
|
||||||
list_del(&p->list);
|
list_del(&p->list);
|
||||||
|
mutex_unlock(&pdev_list_mutex);
|
||||||
kfree(p);
|
kfree(p);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&pdev_list_mutex);
|
mutex_unlock(&pdev_list_mutex);
|
||||||
|
@ -273,7 +277,6 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = {
|
||||||
static int __init via_cputemp_init(void)
|
static int __init via_cputemp_init(void)
|
||||||
{
|
{
|
||||||
int i, err;
|
int i, err;
|
||||||
struct pdev_entry *p, *n;
|
|
||||||
|
|
||||||
if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
|
if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
|
||||||
printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
|
printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
|
||||||
|
@ -295,33 +298,27 @@ static int __init via_cputemp_init(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c->x86_model > 0x0f) {
|
if (c->x86_model > 0x0f) {
|
||||||
printk(KERN_WARNING DRVNAME ": Unknown CPU "
|
pr_warn("Unknown CPU model 0x%x\n", c->x86_model);
|
||||||
"model 0x%x\n", c->x86_model);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = via_cputemp_device_add(i);
|
via_cputemp_device_add(i);
|
||||||
if (err)
|
|
||||||
goto exit_devices_unreg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_HOTPLUG_CPU
|
||||||
if (list_empty(&pdev_list)) {
|
if (list_empty(&pdev_list)) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto exit_driver_unreg;
|
goto exit_driver_unreg;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
register_hotcpu_notifier(&via_cputemp_cpu_notifier);
|
register_hotcpu_notifier(&via_cputemp_cpu_notifier);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
exit_devices_unreg:
|
#ifndef CONFIG_HOTPLUG_CPU
|
||||||
mutex_lock(&pdev_list_mutex);
|
|
||||||
list_for_each_entry_safe(p, n, &pdev_list, list) {
|
|
||||||
platform_device_unregister(p->pdev);
|
|
||||||
list_del(&p->list);
|
|
||||||
kfree(p);
|
|
||||||
}
|
|
||||||
mutex_unlock(&pdev_list_mutex);
|
|
||||||
exit_driver_unreg:
|
exit_driver_unreg:
|
||||||
platform_driver_unregister(&via_cputemp_driver);
|
platform_driver_unregister(&via_cputemp_driver);
|
||||||
|
#endif
|
||||||
exit:
|
exit:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
Warning - only supports a single device.
|
Warning - only supports a single device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
@ -791,21 +793,19 @@ static int __devinit via686a_device_add(unsigned short address)
|
||||||
pdev = platform_device_alloc("via686a", address);
|
pdev = platform_device_alloc("via686a", address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR "via686a: Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "via686a: Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "via686a: Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -1254,8 +1256,7 @@ static int __init vt1211_device_add(unsigned short address)
|
||||||
pdev = platform_device_alloc(DRVNAME, address);
|
pdev = platform_device_alloc(DRVNAME, address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n",
|
pr_err("Device allocation failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1266,15 +1267,13 @@ static int __init vt1211_device_add(unsigned short address)
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto EXIT_DEV_PUT;
|
goto EXIT_DEV_PUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto EXIT_DEV_PUT;
|
goto EXIT_DEV_PUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1301,23 +1300,20 @@ static int __init vt1211_find(int sio_cip, unsigned short *address)
|
||||||
superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
|
superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
|
||||||
|
|
||||||
if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
|
if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
|
||||||
printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
|
pr_warn("HW monitor is disabled, skipping\n");
|
||||||
"skipping\n");
|
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
*address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
|
*address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
|
||||||
(superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
|
(superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
|
||||||
if (*address == 0) {
|
if (*address == 0) {
|
||||||
printk(KERN_WARNING DRVNAME ": Base address is not set, "
|
pr_warn("Base address is not set, skipping\n");
|
||||||
"skipping\n");
|
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
|
pr_info("Found VT1211 chip at 0x%04x, revision %u\n",
|
||||||
"revision %u\n", *address,
|
*address, superio_inb(sio_cip, SIO_VT1211_DEVREV));
|
||||||
superio_inb(sio_cip, SIO_VT1211_DEVREV));
|
|
||||||
|
|
||||||
EXIT:
|
EXIT:
|
||||||
superio_exit(sio_cip);
|
superio_exit(sio_cip);
|
||||||
|
@ -1336,14 +1332,14 @@ static int __init vt1211_init(void)
|
||||||
|
|
||||||
if ((uch_config < -1) || (uch_config > 31)) {
|
if ((uch_config < -1) || (uch_config > 31)) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. "
|
pr_warn("Invalid UCH configuration %d. "
|
||||||
"Choose a value between 0 and 31.\n", uch_config);
|
"Choose a value between 0 and 31.\n", uch_config);
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int_mode < -1) || (int_mode > 0)) {
|
if ((int_mode < -1) || (int_mode > 0)) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. "
|
pr_warn("Invalid interrupt mode %d. "
|
||||||
"Only mode 0 is supported.\n", int_mode);
|
"Only mode 0 is supported.\n", int_mode);
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
/* Supports VIA VT8231 South Bridge embedded sensors
|
/* Supports VIA VT8231 South Bridge embedded sensors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -902,21 +904,19 @@ static int __devinit vt8231_device_add(unsigned short address)
|
||||||
pdev = platform_device_alloc("vt8231", address);
|
pdev = platform_device_alloc("vt8231", address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR "vt8231: Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "vt8231: Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "vt8231: Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3
|
w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -1668,8 +1670,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (val != 0xffff)
|
if (val != 0xffff)
|
||||||
pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
|
pr_debug("unsupported chip ID: 0x%04x\n", val);
|
||||||
val);
|
|
||||||
superio_exit(sioaddr);
|
superio_exit(sioaddr);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -1680,8 +1681,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
|
||||||
| superio_inb(sioaddr, SIO_REG_ADDR + 1);
|
| superio_inb(sioaddr, SIO_REG_ADDR + 1);
|
||||||
*addr = val & IOREGION_ALIGNMENT;
|
*addr = val & IOREGION_ALIGNMENT;
|
||||||
if (*addr == 0) {
|
if (*addr == 0) {
|
||||||
printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O "
|
pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
|
||||||
"device with a base I/O port 0.\n");
|
|
||||||
superio_exit(sioaddr);
|
superio_exit(sioaddr);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -1689,13 +1689,12 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
|
||||||
/* Activate logical device if needed */
|
/* Activate logical device if needed */
|
||||||
val = superio_inb(sioaddr, SIO_REG_ENABLE);
|
val = superio_inb(sioaddr, SIO_REG_ENABLE);
|
||||||
if (!(val & 0x01)) {
|
if (!(val & 0x01)) {
|
||||||
printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. "
|
pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
|
||||||
"Sensor is probably unusable.\n");
|
|
||||||
superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
|
superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
superio_exit(sioaddr);
|
superio_exit(sioaddr);
|
||||||
pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr);
|
pr_info("Found %s chip at %#x\n", sio_name, *addr);
|
||||||
sio_data->sioreg = sioaddr;
|
sio_data->sioreg = sioaddr;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1729,14 +1728,14 @@ static int __init sensors_w83627ehf_init(void)
|
||||||
|
|
||||||
if (!(pdev = platform_device_alloc(DRVNAME, address))) {
|
if (!(pdev = platform_device_alloc(DRVNAME, address))) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit_unregister;
|
goto exit_unregister;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_data(pdev, &sio_data,
|
err = platform_device_add_data(pdev, &sio_data,
|
||||||
sizeof(struct w83627ehf_sio_data));
|
sizeof(struct w83627ehf_sio_data));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
|
pr_err("Platform data allocation failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1752,16 +1751,14 @@ static int __init sensors_w83627ehf_init(void)
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* platform_device_add calls probe() */
|
/* platform_device_add calls probe() */
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
supported yet.
|
supported yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -1166,14 +1168,13 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
|
||||||
superio_inb(sio_data, WINB_BASE_REG + 1);
|
superio_inb(sio_data, WINB_BASE_REG + 1);
|
||||||
*addr = val & WINB_ALIGNMENT;
|
*addr = val & WINB_ALIGNMENT;
|
||||||
if (*addr == 0) {
|
if (*addr == 0) {
|
||||||
printk(KERN_WARNING DRVNAME ": Base address not set, "
|
pr_warn("Base address not set, skipping\n");
|
||||||
"skipping\n");
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = superio_inb(sio_data, WINB_ACT_REG);
|
val = superio_inb(sio_data, WINB_ACT_REG);
|
||||||
if (!(val & 0x01)) {
|
if (!(val & 0x01)) {
|
||||||
printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
|
pr_warn("Enabling HWM logical device\n");
|
||||||
superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
|
superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1789,28 +1790,26 @@ static int __init w83627hf_device_add(unsigned short address,
|
||||||
pdev = platform_device_alloc(DRVNAME, address);
|
pdev = platform_device_alloc(DRVNAME, address);
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
pr_err("Device allocation failed\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_resources(pdev, &res, 1);
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
pr_err("Device resource addition failed (%d)\n", err);
|
||||||
"(%d)\n", err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add_data(pdev, sio_data,
|
err = platform_device_add_data(pdev, sio_data,
|
||||||
sizeof(struct w83627hf_sio_data));
|
sizeof(struct w83627hf_sio_data));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
|
pr_err("Platform data allocation failed\n");
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = platform_device_add(pdev);
|
err = platform_device_add(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
pr_err("Device addition failed (%d)\n", err);
|
||||||
err);
|
|
||||||
goto exit_device_put;
|
goto exit_device_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
include/linux/i2c/ds620.h
Normal file
21
include/linux/i2c/ds620.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef _LINUX_DS620_H
|
||||||
|
#define _LINUX_DS620_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
|
||||||
|
/* platform data for the DS620 temperature sensor and thermostat */
|
||||||
|
|
||||||
|
struct ds620_platform_data {
|
||||||
|
/*
|
||||||
|
* Thermostat output pin PO mode:
|
||||||
|
* 0 = always low (default)
|
||||||
|
* 1 = PO_LOW
|
||||||
|
* 2 = PO_HIGH
|
||||||
|
*
|
||||||
|
* (see Documentation/hwmon/ds620)
|
||||||
|
*/
|
||||||
|
int pomode;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _LINUX_DS620_H */
|
Loading…
Reference in a new issue