1
0
Fork 0

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>
  ...
hifive-unleashed-5.1
Linus Torvalds 2011-01-10 08:57:46 -08:00
commit a08948812b
36 changed files with 1837 additions and 1556 deletions

View 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.

View 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.

View File

@ -384,10 +384,20 @@ curr[1-*]_min Current min value.
Unit: milliampere
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
Unit: milliampere
RO
Also see the Alarms section for status flags associated with currents.
*********
* Power *
*********
@ -450,13 +460,6 @@ power[1-*]_accuracy Accuracy of the power meter.
Unit: Percent
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
system should take action to reduce power use.
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
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 *
**********
@ -488,6 +505,15 @@ energy[1-*]_input Cumulative energy use
RO
************
* Humidity *
************
humidity[1-*]_input Humidity
Unit: milli-percent (per cent mille, pcm)
RO
**********
* Alarms *
**********
@ -501,6 +527,7 @@ implementation.
in[0-*]_alarm
curr[1-*]_alarm
power[1-*]_alarm
fan[1-*]_alarm
temp[1-*]_alarm
Channel alarm
@ -512,12 +539,20 @@ OR
in[0-*]_min_alarm
in[0-*]_max_alarm
in[0-*]_lcrit_alarm
in[0-*]_crit_alarm
curr[1-*]_min_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-*]_max_alarm
temp[1-*]_min_alarm
temp[1-*]_max_alarm
temp[1-*]_lcrit_alarm
temp[1-*]_crit_alarm
temp[1-*]_emergency_alarm
Limit alarm

View File

@ -274,6 +274,16 @@ config SENSORS_ATXP1
This driver can also be built as a module. If so, the module
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
tristate "Dallas Semiconductor DS1621 and DS1625"
depends on I2C
@ -734,6 +744,16 @@ config SENSORS_SHT15
This driver can also be built as a module. If so, the module
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
tristate "Samsung built-in ADC"
depends on S3C_ADC

View File

@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
obj-$(CONFIG_SENSORS_DS620) += ds620.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EMC1403) += emc1403.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_S3C) += s3c-hwmon.o
obj-$(CONFIG_SENSORS_SHT15) += sht15.o
obj-$(CONFIG_SENSORS_SHT21) += sht21.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMM665) += smm665.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o

View File

@ -20,6 +20,9 @@
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!
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/init.h>
@ -220,6 +223,10 @@ struct abituguru_data {
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 */
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. */
if ((val < 10u) || (val > 250u)) {
printk(KERN_WARNING ABIT_UGURU_NAME
": bank1-sensor: %d reading (%d) too close to limits, "
pr_warn("bank1-sensor: %d reading (%d) too close to limits, "
"unable to determine sensor type, skipping sensor\n",
(int)sensor_addr, (int)val);
/* assume no sensor is there for sensors for which we can't
@ -535,10 +541,8 @@ abituguru_detect_bank1_sensor_type_exit:
3) == 3)
break;
if (i == 3) {
printk(KERN_ERR ABIT_UGURU_NAME
": Fatal error could not restore original settings. "
"This should never happen please report this to the "
"abituguru maintainer (see MAINTAINERS)\n");
pr_err("Fatal error could not restore original settings. %s %s\n",
never_happen, report_this);
return -ENODEV;
}
return ret;
@ -1268,14 +1272,12 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
}
/* Fail safe check, this should never happen! */
if (sysfs_names_free < 0) {
printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of "
"space for sysfs attr names. This should never "
"happen please report to the abituguru maintainer "
"(see MAINTAINERS)\n");
pr_err("Fatal error ran out of space for sysfs attr names. %s %s",
never_happen, report_this);
res = -ENAMETOOLONG;
goto abituguru_probe_error;
}
printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
pr_info("found Abit uGuru\n");
/* Register sysfs hooks */
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);
if (force) {
printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is "
"present because of \"force\" parameter\n");
pr_info("Assuming Abit uGuru is present because of \"force\" parameter\n");
return ABIT_UGURU_BASE;
}
@ -1467,8 +1468,7 @@ static int __init abituguru_init(void)
abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address);
if (!abituguru_pdev) {
printk(KERN_ERR ABIT_UGURU_NAME
": Device allocation failed\n");
pr_err("Device allocation failed\n");
err = -ENOMEM;
goto exit_driver_unregister;
}
@ -1479,15 +1479,13 @@ static int __init abituguru_init(void)
err = platform_device_add_resources(abituguru_pdev, &res, 1);
if (err) {
printk(KERN_ERR ABIT_UGURU_NAME
": Device resource addition failed (%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(abituguru_pdev);
if (err) {
printk(KERN_ERR ABIT_UGURU_NAME
": Device addition failed (%d)\n", err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -23,6 +23,9 @@
chip found on newer Abit uGuru motherboards. Note: because of lack of specs
only reading the sensors and their settings is supported.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@ -608,6 +611,9 @@ static int verbose = 1;
module_param(verbose, bool, 0644);
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) */
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)
break;
if (!abituguru3_motherboards[i].id) {
printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard "
"ID: %04X. Please report this to the abituguru3 "
"maintainer (see MAINTAINERS)\n", (unsigned int)id);
pr_err("error unknown motherboard ID: %04X. %s\n",
(unsigned int)id, report_this);
goto abituguru3_probe_error;
}
data->sensors = abituguru3_motherboards[i].sensors;
printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
"ID: %04X\n", (unsigned int)id);
pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id);
/* Fill the sysfs attr array */
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++) {
/* Fail safe check, this should never happen! */
if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
printk(KERN_ERR ABIT_UGURU3_NAME
": Fatal error motherboard has more sensors "
"then ABIT_UGURU3_MAX_NO_SENSORS. This should "
"never happen please report to the abituguru3 "
"maintainer (see MAINTAINERS)\n");
pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n",
never_happen, report_this);
res = -ENAMETOOLONG;
goto abituguru3_probe_error;
}
@ -983,10 +984,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
}
/* Fail safe check, this should never happen! */
if (sysfs_names_free < 0) {
printk(KERN_ERR ABIT_UGURU3_NAME
": Fatal error ran out of space for sysfs attr names. "
"This should never happen please report to the "
"abituguru3 maintainer (see MAINTAINERS)\n");
pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n",
never_happen, report_this);
res = -ENAMETOOLONG;
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);
if (force) {
printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
"present because of \"force\" parameter\n");
pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n");
return 0;
}
@ -1219,10 +1217,8 @@ static int __init abituguru3_init(void)
return err;
#ifdef CONFIG_DMI
printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
"not detected using DMI. Please send the output of "
"\"dmidecode\" to the abituguru3 maintainer "
"(see MAINTAINERS)\n");
pr_warn("this motherboard was not detected using DMI. "
"Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n");
#endif
}
@ -1233,8 +1229,7 @@ static int __init abituguru3_init(void)
abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME,
ABIT_UGURU3_BASE);
if (!abituguru3_pdev) {
printk(KERN_ERR ABIT_UGURU3_NAME
": Device allocation failed\n");
pr_err("Device allocation failed\n");
err = -ENOMEM;
goto exit_driver_unregister;
}
@ -1245,15 +1240,13 @@ static int __init abituguru3_init(void)
err = platform_device_add_resources(abituguru3_pdev, &res, 1);
if (err) {
printk(KERN_ERR ABIT_UGURU3_NAME
": Device resource addition failed (%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(abituguru3_pdev);
if (err) {
printk(KERN_ERR ABIT_UGURU3_NAME
": Device addition failed (%d)\n", err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -19,6 +19,8 @@
* 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/jiffies.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]);
if (res) {
printk(KERN_ERR "ha ha, interrupted");
pr_err("ha ha, interrupted\n");
return -EAGAIN;
}

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,8 @@
asb100 7 3 1 4 0x31 0x0694 yes no
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
@ -701,8 +703,7 @@ static int asb100_detect(struct i2c_client *client,
int val1, val2;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("asb100.o: detect failed, "
"smbus byte data not supported!\n");
pr_debug("detect failed, smbus byte data not supported!\n");
return -ENODEV;
}
@ -715,7 +716,7 @@ static int asb100_detect(struct i2c_client *client,
(((!(val1 & 0x80)) && (val2 != 0x94)) ||
/* Check for ASB100 ID (high byte ) */
((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;
}
@ -744,7 +745,7 @@ static int asb100_probe(struct i2c_client *client,
data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL);
if (!data) {
pr_debug("asb100.o: probe failed, kzalloc failed!\n");
pr_debug("probe failed, kzalloc failed!\n");
err = -ENOMEM;
goto ERROR0;
}

View File

@ -5,6 +5,8 @@
* See COPYING in the top level directory of the kernel tree.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/debugfs.h>
#include <linux/kernel.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 */
if (!acpi_resources_are_enforced()) {
pr_err("atk: Resources not safely usable due to "
"acpi_enforce_resources kernel parameter\n");
pr_err("Resources not safely usable due to acpi_enforce_resources kernel parameter\n");
return -EBUSY;
}
ret = acpi_bus_register_driver(&atk_driver);
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;
}

View File

@ -20,6 +20,8 @@
* 02110-1301 USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.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.
*/
if (!cpu_has(c, X86_FEATURE_DTS)) {
printk(KERN_INFO DRVNAME ": CPU (model=0x%x)"
" has no thermal sensor.\n", c->x86_model);
pr_info("CPU (model=0x%x) has no thermal sensor\n",
c->x86_model);
return 0;
}
@ -466,7 +468,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
pdev = platform_device_alloc(DRVNAME, cpu);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
@ -478,8 +480,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_free;
}

View File

@ -25,6 +25,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.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 */
if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
dme1737_sio_inb(sio_cip, 0x61))) {
printk(KERN_ERR "dme1737: Base address not set.\n");
pr_err("Base address not set\n");
err = -ENODEV;
goto exit;
}
@ -2475,20 +2477,18 @@ static int __init dme1737_isa_device_add(unsigned short addr)
goto exit;
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;
goto exit;
}
if ((err = platform_device_add_resources(pdev, &res, 1))) {
printk(KERN_ERR "dme1737: Failed to add device resource "
"(err = %d).\n", err);
pr_err("Failed to add device resource (err = %d)\n", err);
goto exit_device_put;
}
if ((err = platform_device_add(pdev))) {
printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n",
err);
pr_err("Failed to add device (err = %d)\n", err);
goto exit_device_put;
}

View 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);

View File

@ -28,6 +28,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.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))) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Out of memory\n");
pr_err("Out of memory\n");
goto exit;
}
@ -1451,7 +1453,7 @@ static int __init f71805f_device_add(unsigned short address,
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
@ -1462,22 +1464,20 @@ static int __init f71805f_device_add(unsigned short address,
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add_data(pdev, sio_data,
sizeof(struct f71805f_sio_data));
if (err) {
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
pr_err("Platform data allocation failed\n");
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}
@ -1516,30 +1516,27 @@ static int __init f71805f_find(int sioaddr, unsigned short *address,
sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
break;
default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
"skipping\n");
pr_info("Unsupported Fintek device, skipping\n");
goto exit;
}
superio_select(sioaddr, F71805F_LD_HWM);
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
printk(KERN_WARNING DRVNAME ": Device not activated, "
"skipping\n");
pr_warn("Device not activated, skipping\n");
goto exit;
}
*address = superio_inw(sioaddr, SIO_REG_ADDR);
if (*address == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set, "
"skipping\n");
pr_warn("Base address not set, skipping\n");
goto exit;
}
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
err = 0;
printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
names[sio_data->kind], *address,
superio_inb(sioaddr, SIO_REG_DEVREV));
pr_info("Found %s chip at %#x, revision %u\n",
names[sio_data->kind], *address,
superio_inb(sioaddr, SIO_REG_DEVREV));
exit:
superio_exit(sioaddr);

View File

@ -18,6 +18,8 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.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 */
if (!request_muxed_region(base, 2, DRVNAME)) {
printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
base);
pr_err("I/O address 0x%04x already in use\n", base);
return -EBUSY;
}
@ -2192,7 +2193,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
devid = superio_inw(sioaddr, SIO_REG_MANID);
if (devid != SIO_FINTEK_ID) {
pr_debug(DRVNAME ": Not a Fintek device\n");
pr_debug("Not a Fintek device\n");
err = -ENODEV;
goto exit;
}
@ -2215,8 +2216,8 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
sio_data->type = f8000;
break;
default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
(unsigned int)devid);
pr_info("Unsupported Fintek device: %04x\n",
(unsigned int)devid);
err = -ENODEV;
goto exit;
}
@ -2227,21 +2228,21 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
superio_select(sioaddr, SIO_F71882FG_LD_HWM);
if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
printk(KERN_WARNING DRVNAME ": Device not activated\n");
pr_warn("Device not activated\n");
err = -ENODEV;
goto exit;
}
*address = superio_inw(sioaddr, SIO_REG_ADDR);
if (*address == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set\n");
pr_warn("Base address not set\n");
err = -ENODEV;
goto exit;
}
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
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,
(int)superio_inb(sioaddr, SIO_REG_DEVREV));
exit:
@ -2270,20 +2271,20 @@ static int __init f71882fg_device_add(unsigned short address,
err = platform_device_add_resources(f71882fg_pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
pr_err("Device resource addition failed\n");
goto exit_device_put;
}
err = platform_device_add_data(f71882fg_pdev, sio_data,
sizeof(struct f71882fg_sio_data));
if (err) {
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
pr_err("Platform data allocation failed\n");
goto exit_device_put;
}
err = platform_device_add(f71882fg_pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed\n");
pr_err("Device addition failed\n");
goto exit_device_put;
}

View File

@ -20,6 +20,8 @@
* 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/init.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)
{
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;
}
@ -303,11 +305,10 @@ static int lis3lv02d_add(struct acpi_device *device)
/* If possible use a "standard" axes order */
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",
lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
pr_info("Using custom axes %d,%d,%d\n",
lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
"using default axes configuration\n");
pr_info("laptop model unknown, using default axes configuration\n");
lis3_dev.ac = lis3lv02d_axis_normal;
}
@ -385,7 +386,7 @@ static int __init lis3lv02d_init_module(void)
if (ret < 0)
return ret;
printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
pr_info("driver loaded\n");
return 0;
}

View File

@ -22,6 +22,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.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);
default: /* report 0 for unknown */
if (vrm)
printk(KERN_WARNING "hwmon-vid: Requested unsupported "
"VRM version (%u)\n", (unsigned int)vrm);
pr_warn("Requested unsupported VRM version (%u)\n",
(unsigned int)vrm);
return 0;
}
}
@ -246,8 +248,7 @@ u8 vid_which_vrm(void)
}
vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
if (vrm_ret == 0)
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
"x86 CPU\n");
pr_info("Unknown VRM version of your x86 CPU\n");
return vrm_ret;
}
@ -255,7 +256,7 @@ u8 vid_which_vrm(void)
#else
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;
}
#endif

View File

@ -10,6 +10,8 @@
the Free Software Foundation; version 2 of the License.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/device.h>
#include <linux/err.h>
@ -119,7 +121,7 @@ static int __init hwmon_init(void)
hwmon_class = class_create(THIS_MODULE, "hwmon");
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 0;

View File

@ -20,6 +20,8 @@
* 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/module.h>
#include <linux/hwmon.h>
@ -1090,7 +1092,7 @@ static int __init aem_init(void)
res = driver_register(&aem_driver.driver);
if (res) {
printk(KERN_ERR "Can't register aem driver\n");
pr_err("Can't register aem driver\n");
return res;
}

View File

@ -20,6 +20,8 @@
* 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/init.h>
#include <linux/dmi.h>
@ -860,8 +862,7 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
(p->irq_flags2 & IRQF_TRIGGER_MASK),
DRIVER_NAME, &lis3_dev);
if (err < 0)
printk(KERN_ERR DRIVER_NAME
"No second IRQ. Limited functionality\n");
pr_err("No second IRQ. Limited functionality\n");
}
}
@ -879,7 +880,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
switch (dev->whoami) {
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->mdps_max_val = 2048;
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);
break;
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->mdps_max_val = 128;
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);
break;
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->mdps_max_val = 128;
dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
@ -910,8 +911,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
dev->scale = LIS3_SENSITIVITY_8B;
break;
default:
printk(KERN_ERR DRIVER_NAME
": unknown sensor type 0x%X\n", dev->whoami);
pr_err("unknown sensor type 0x%X\n", dev->whoami);
return -EINVAL;
}
@ -935,7 +935,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
}
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
* 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 */
if (!dev->irq) {
printk(KERN_ERR DRIVER_NAME
": No IRQ. Disabling /dev/freefall\n");
pr_err("No IRQ. Disabling /dev/freefall\n");
goto out;
}
@ -985,12 +984,12 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
DRIVER_NAME, &lis3_dev);
if (err < 0) {
printk(KERN_ERR DRIVER_NAME "Cannot get IRQ\n");
pr_err("Cannot get IRQ\n");
goto out;
}
if (misc_register(&lis3lv02d_misc_device))
printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
pr_err("misc_register failed\n");
out:
return 0;
}

View File

@ -24,6 +24,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/module.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);
if (status < 0) {
printk(KERN_WARNING
"spi_write_then_read failed with status %d\n", status);
pr_warn("spi_write_then_read failed with status %d\n", status);
goto out;
}
raw = (rxbuf[0] << 8) + rxbuf[1];

View File

@ -1,13 +1,9 @@
/*
* lm95241.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com>
* Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
*
* Based on the max1619 driver. The LM95241 is a sensor chip made by National
* Semiconductors.
* It reports up to three temperatures (its own plus up to
* two external ones). Complete datasheet can be
* obtained from National's website at:
* The LM95241 is a sensor chip made by National Semiconductors.
* It reports up to three temperatures (its own plus up to two external ones).
* Complete datasheet can be obtained from National's website at:
* http://www.national.com/ds.cgi/LM/LM95241.pdf
*
* This program is free software; you can redistribute it and/or modify
@ -36,8 +32,10 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
#define DEVNAME "lm95241"
static const unsigned short normal_i2c[] = {
0x19, 0x2a, 0x2b, I2C_CLIENT_END};
0x19, 0x2a, 0x2b, I2C_CLIENT_END };
/* LM95241 registers */
#define LM95241_REG_R_MAN_ID 0xFE
@ -46,7 +44,7 @@ static const unsigned short normal_i2c[] = {
#define LM95241_REG_RW_CONFIG 0x03
#define LM95241_REG_RW_REM_FILTER 0x06
#define LM95241_REG_RW_TRUTHERM 0x07
#define LM95241_REG_W_ONE_SHOT 0x0F
#define LM95241_REG_W_ONE_SHOT 0x0F
#define LM95241_REG_R_LOCAL_TEMPH 0x10
#define LM95241_REG_R_REMOTE1_TEMPH 0x11
#define LM95241_REG_R_REMOTE2_TEMPH 0x12
@ -79,52 +77,205 @@ static const unsigned short normal_i2c[] = {
#define MANUFACTURER_ID 0x01
#define DEFAULT_REVISION 0xA4
/* Conversions and various macros */
#define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \
(val_h)) * 1000 + (val_l) * 1000 / 256)
/* Functions declaration */
static void lm95241_init_client(struct i2c_client *client);
static struct lm95241_data *lm95241_update_device(struct device *dev);
static const u8 lm95241_reg_address[] = {
LM95241_REG_R_LOCAL_TEMPH,
LM95241_REG_R_LOCAL_TEMPL,
LM95241_REG_R_REMOTE1_TEMPH,
LM95241_REG_R_REMOTE1_TEMPL,
LM95241_REG_R_REMOTE2_TEMPH,
LM95241_REG_R_REMOTE2_TEMPL
};
/* Client data (each client gets its own) */
struct lm95241_data {
struct device *hwmon_dev;
struct mutex update_lock;
unsigned long last_updated, interval; /* in jiffies */
char valid; /* zero until following fields are valid */
unsigned long last_updated, interval; /* in jiffies */
char valid; /* zero until following fields are valid */
/* registers values */
u8 local_h, local_l; /* local */
u8 remote1_h, remote1_l; /* remote1 */
u8 remote2_h, remote2_l; /* remote2 */
u8 temp[ARRAY_SIZE(lm95241_reg_address)];
u8 config, model, trutherm;
};
/* Sysfs stuff */
#define show_temp(value) \
static ssize_t show_##value(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct lm95241_data *data = lm95241_update_device(dev); \
snprintf(buf, PAGE_SIZE - 1, "%d\n", \
TEMP_FROM_REG(data->value##_h, data->value##_l)); \
return strlen(buf); \
/* Conversions */
static int TempFromReg(u8 val_h, u8 val_l)
{
if (val_h & 0x80)
return val_h - 0x100;
return val_h * 1000 + val_l * 1000 / 256;
}
show_temp(local);
show_temp(remote1);
show_temp(remote2);
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
char *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);
snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ);
return strlen(buf);
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;
}
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm95241_data *data = lm95241_update_device(dev);
return snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval
/ HZ);
}
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95241_data *data = i2c_get_clientdata(client);
@ -138,176 +289,34 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
return count;
}
#define show_type(flag) \
static ssize_t show_type##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->model & R##flag##MS_MASK ? "1\n" : "2\n"); \
return strlen(buf); \
}
show_type(1);
show_type(2);
#define show_min(flag) \
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 SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
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,
R1MS_MASK);
static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type,
R2MS_MASK);
static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min,
R1DF_MASK);
static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min,
R2DF_MASK);
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max,
R1DF_MASK);
static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max,
R2DF_MASK);
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
set_interval);
static struct attribute *lm95241_attributes[] = {
&dev_attr_temp1_input.attr,
&dev_attr_temp2_input.attr,
&dev_attr_temp3_input.attr,
&dev_attr_temp2_type.attr,
&dev_attr_temp3_type.attr,
&dev_attr_temp2_min.attr,
&dev_attr_temp3_min.attr,
&dev_attr_temp2_max.attr,
&dev_attr_temp3_max.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp2_type.dev_attr.attr,
&sensor_dev_attr_temp3_type.dev_attr.attr,
&sensor_dev_attr_temp2_min.dev_attr.attr,
&sensor_dev_attr_temp3_min.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL
};
@ -329,9 +338,9 @@ static int lm95241_detect(struct i2c_client *new_client,
if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
== MANUFACTURER_ID)
&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
>= DEFAULT_REVISION)) {
name = "lm95241";
&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
>= DEFAULT_REVISION)) {
name = DEVNAME;
} else {
dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
address);
@ -343,6 +352,25 @@ static int lm95241_detect(struct i2c_client *new_client,
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,
const struct i2c_device_id *id)
{
@ -382,26 +410,6 @@ exit:
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)
{
struct lm95241_data *data = i2c_get_clientdata(client);
@ -413,46 +421,9 @@ static int lm95241_remove(struct i2c_client *client)
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) */
static const struct i2c_device_id lm95241_id[] = {
{ "lm95241", 0 },
{ DEVNAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm95241_id);
@ -460,7 +431,7 @@ MODULE_DEVICE_TABLE(i2c, lm95241_id);
static struct i2c_driver lm95241_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "lm95241",
.name = DEVNAME,
},
.probe = lm95241_probe,
.remove = lm95241_remove,
@ -479,7 +450,7 @@ static void __exit sensors_lm95241_exit(void)
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_LICENSE("GPL");

View File

@ -18,6 +18,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@ -290,8 +292,7 @@ static struct i2c_driver pcf8591_driver = {
static int __init pcf8591_init(void)
{
if (input_mode < 0 || input_mode > 3) {
printk(KERN_WARNING "pcf8591: invalid input_mode (%d)\n",
input_mode);
pr_warn("invalid input_mode (%d)\n", input_mode);
input_mode = 0;
}
return i2c_add_driver(&pcf8591_driver);

View File

@ -20,6 +20,8 @@
* 02110-1301 USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@ -303,7 +305,7 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu)
pdev = platform_device_alloc(DRVNAME, cpu);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
@ -315,8 +317,7 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu)
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_free;
}

View 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");

View File

@ -50,6 +50,8 @@
735 0008 0735
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
@ -735,21 +737,19 @@ static int __devinit sis5595_device_add(unsigned short address)
pdev = platform_device_alloc("sis5595", address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR "sis5595: Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR "sis5595: Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR "sis5595: Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -26,6 +26,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
@ -311,21 +313,19 @@ static int __init smsc47b397_device_add(unsigned short address)
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}
@ -367,8 +367,7 @@ static int __init smsc47b397_find(unsigned short *addr)
*addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
| superio_inb(SUPERIO_REG_BASE_LSB);
printk(KERN_INFO DRVNAME ": found SMSC %s "
"(base address 0x%04x, revision %u)\n",
pr_info("found SMSC %s (base address 0x%04x, revision %u)\n",
name, *addr, rev);
superio_exit();

View File

@ -26,6 +26,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
@ -435,30 +437,29 @@ static int __init smsc47m1_find(unsigned short *addr,
*/
switch (val) {
case 0x51:
pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
pr_info("Found SMSC LPC47B27x\n");
sio_data->type = smsc47m1;
break;
case 0x59:
pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
pr_info("Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
sio_data->type = smsc47m1;
break;
case 0x5F:
pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
pr_info("Found SMSC LPC47M14x\n");
sio_data->type = smsc47m1;
break;
case 0x60:
pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
pr_info("Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
sio_data->type = smsc47m1;
break;
case 0x6B:
if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
pr_debug(DRVNAME ": "
"Found SMSC LPC47M233, unsupported\n");
pr_debug("Found SMSC LPC47M233, unsupported\n");
superio_exit();
return -ENODEV;
}
pr_info(DRVNAME ": Found SMSC LPC47M292\n");
pr_info("Found SMSC LPC47M292\n");
sio_data->type = smsc47m2;
break;
default:
@ -470,7 +471,7 @@ static int __init smsc47m1_find(unsigned short *addr,
*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
| superio_inb(SUPERIO_REG_BASE + 1);
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();
return -ENODEV;
}
@ -479,7 +480,7 @@ static int __init smsc47m1_find(unsigned short *addr,
* Compaq Presario S4000NX) */
sio_data->activate = superio_inb(SUPERIO_REG_ACT);
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);
}
@ -494,7 +495,7 @@ static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
superio_enter();
superio_select();
pr_info(DRVNAME ": Disabling device\n");
pr_info("Disabling device\n");
superio_outb(SUPERIO_REG_ACT, sio_data->activate);
superio_exit();
@ -823,28 +824,26 @@ static int __init smsc47m1_device_add(unsigned short address,
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add_data(pdev, sio_data,
sizeof(struct smsc47m1_sio_data));
if (err) {
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
pr_err("Platform data allocation failed\n");
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -21,6 +21,8 @@
* 02110-1301 USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.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);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
@ -214,8 +216,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu)
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_free;
}
@ -237,13 +238,16 @@ exit:
static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
{
struct pdev_entry *p, *n;
struct pdev_entry *p;
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) {
platform_device_unregister(p->pdev);
list_del(&p->list);
mutex_unlock(&pdev_list_mutex);
kfree(p);
return;
}
}
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)
{
int i, err;
struct pdev_entry *p, *n;
if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
@ -295,33 +298,27 @@ static int __init via_cputemp_init(void)
continue;
if (c->x86_model > 0x0f) {
printk(KERN_WARNING DRVNAME ": Unknown CPU "
"model 0x%x\n", c->x86_model);
pr_warn("Unknown CPU model 0x%x\n", c->x86_model);
continue;
}
err = via_cputemp_device_add(i);
if (err)
goto exit_devices_unreg;
via_cputemp_device_add(i);
}
#ifndef CONFIG_HOTPLUG_CPU
if (list_empty(&pdev_list)) {
err = -ENODEV;
goto exit_driver_unreg;
}
#endif
register_hotcpu_notifier(&via_cputemp_cpu_notifier);
return 0;
exit_devices_unreg:
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);
#ifndef CONFIG_HOTPLUG_CPU
exit_driver_unreg:
platform_driver_unregister(&via_cputemp_driver);
#endif
exit:
return err;
}

View File

@ -30,6 +30,8 @@
Warning - only supports a single device.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
@ -791,21 +793,19 @@ static int __devinit via686a_device_add(unsigned short address)
pdev = platform_device_alloc("via686a", address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR "via686a: Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR "via686a: Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR "via686a: Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -21,6 +21,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@ -1254,8 +1256,7 @@ static int __init vt1211_device_add(unsigned short address)
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n",
err);
pr_err("Device allocation failed (%d)\n", err);
goto EXIT;
}
@ -1266,15 +1267,13 @@ static int __init vt1211_device_add(unsigned short address)
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto EXIT_DEV_PUT;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
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);
if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
"skipping\n");
pr_warn("HW monitor is disabled, skipping\n");
goto EXIT;
}
*address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
(superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
if (*address == 0) {
printk(KERN_WARNING DRVNAME ": Base address is not set, "
"skipping\n");
pr_warn("Base address is not set, skipping\n");
goto EXIT;
}
err = 0;
printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
"revision %u\n", *address,
superio_inb(sio_cip, SIO_VT1211_DEVREV));
pr_info("Found VT1211 chip at 0x%04x, revision %u\n",
*address, superio_inb(sio_cip, SIO_VT1211_DEVREV));
EXIT:
superio_exit(sio_cip);
@ -1336,15 +1332,15 @@ static int __init vt1211_init(void)
if ((uch_config < -1) || (uch_config > 31)) {
err = -EINVAL;
printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. "
"Choose a value between 0 and 31.\n", uch_config);
pr_warn("Invalid UCH configuration %d. "
"Choose a value between 0 and 31.\n", uch_config);
goto EXIT;
}
if ((int_mode < -1) || (int_mode > 0)) {
err = -EINVAL;
printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. "
"Only mode 0 is supported.\n", int_mode);
pr_warn("Invalid interrupt mode %d. "
"Only mode 0 is supported.\n", int_mode);
goto EXIT;
}

View File

@ -24,6 +24,8 @@
/* Supports VIA VT8231 South Bridge embedded sensors
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@ -902,21 +904,19 @@ static int __devinit vt8231_device_add(unsigned short address)
pdev = platform_device_alloc("vt8231", address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR "vt8231: Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR "vt8231: Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR "vt8231: Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -42,6 +42,8 @@
w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@ -1668,8 +1670,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
break;
default:
if (val != 0xffff)
pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
val);
pr_debug("unsupported chip ID: 0x%04x\n", val);
superio_exit(sioaddr);
return -ENODEV;
}
@ -1680,8 +1681,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
| superio_inb(sioaddr, SIO_REG_ADDR + 1);
*addr = val & IOREGION_ALIGNMENT;
if (*addr == 0) {
printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O "
"device with a base I/O port 0.\n");
pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
superio_exit(sioaddr);
return -ENODEV;
}
@ -1689,13 +1689,12 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
/* Activate logical device if needed */
val = superio_inb(sioaddr, SIO_REG_ENABLE);
if (!(val & 0x01)) {
printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. "
"Sensor is probably unusable.\n");
pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
}
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;
return 0;
@ -1729,14 +1728,14 @@ static int __init sensors_w83627ehf_init(void)
if (!(pdev = platform_device_alloc(DRVNAME, address))) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit_unregister;
}
err = platform_device_add_data(pdev, &sio_data,
sizeof(struct w83627ehf_sio_data));
if (err) {
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
pr_err("Platform data allocation failed\n");
goto exit_device_put;
}
@ -1752,16 +1751,14 @@ static int __init sensors_w83627ehf_init(void)
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
/* platform_device_add calls probe() */
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View File

@ -39,6 +39,8 @@
supported yet.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.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);
*addr = val & WINB_ALIGNMENT;
if (*addr == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set, "
"skipping\n");
pr_warn("Base address not set, skipping\n");
goto exit;
}
val = superio_inb(sio_data, WINB_ACT_REG);
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);
}
@ -1789,28 +1790,26 @@ static int __init w83627hf_device_add(unsigned short address,
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
pr_err("Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
pr_err("Device resource addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_device_add_data(pdev, sio_data,
sizeof(struct w83627hf_sio_data));
if (err) {
printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
pr_err("Platform data allocation failed\n");
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}

View 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 */