Commit d1e0fe25 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: (23 commits)
  hwmon: (lm75) Add support for the Texas Instruments TMP105
  hwmon: (ltc4245) Read only one GPIO pin
  hwmon: (dme1737) Add SCH5127 support
  hwmon: (tmp102) Don't always stop chip at exit
  hwmon: (tmp102) Fix suspend and resume functions
  hwmon: (tmp102) Various fixes
  hwmon: Driver for TI TMP102 temperature sensor
  hwmon: EMC1403 thermal sensor support
  hwmon: (applesmc) Add temperature sensor labels to sysfs interface
  hwmon: (applesmc) Add generic support for MacBook Pro 7
  hwmon: (applesmc) Add generic support for MacBook Pro 6
  hwmon: (applesmc) Add support for MacBook Pro 5,3 and 5,4
  hwmon: (tmp401) Reorganize code to get rid of static forward declarations
  hwmon: (tmp401) Use constants for sysfs file permissions
  hwmon: (adm1031) Allow setting update rate
  hwmon: Add description of the update_rate sysfs attribute
  hwmon: (lm90) Use programmed update rate
  hwmon: (f71882fg) Acquire I/O regions while we're working with them
  hwmon: (f71882fg) Code cleanup
  hwmon: (f71882fg) Use strict_stro(l|ul) instead of simple_strto$1
  ...
parents cc106eb3 6d034059
......@@ -9,11 +9,15 @@ Supported chips:
* SMSC SCH3112, SCH3114, SCH3116
Prefix: 'sch311x'
Addresses scanned: none, address read from Super-I/O config space
Datasheet: http://www.nuhorizons.com/FeaturedProducts/Volume1/SMSC/311x.pdf
Datasheet: Available on the Internet
* SMSC SCH5027
Prefix: 'sch5027'
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
Datasheet: Provided by SMSC upon request and under NDA
* SMSC SCH5127
Prefix: 'sch5127'
Addresses scanned: none, address read from Super-I/O config space
Datasheet: Provided by SMSC upon request and under NDA
Authors:
Juerg Haefliger <juergh@gmail.com>
......@@ -36,8 +40,8 @@ Description
-----------
This driver implements support for the hardware monitoring capabilities of the
SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, and SMSC
SCH311x Super-I/O chips. These chips feature monitoring of 3 temp sensors
SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, SCH311x,
and SCH5127 Super-I/O chips. These chips feature monitoring of 3 temp sensors
temp[1-3] (2 remote diodes and 1 internal), 7 voltages in[0-6] (6 external and
1 internal) and up to 6 fan speeds fan[1-6]. Additionally, the chips implement
up to 5 PWM outputs pwm[1-3,5-6] for controlling fan speeds both manually and
......@@ -48,14 +52,14 @@ Fan[3-6] and pwm[3,5-6] are optional features and their availability depends on
the configuration of the chip. The driver will detect which features are
present during initialization and create the sysfs attributes accordingly.
For the SCH311x, fan[1-3] and pwm[1-3] are always present and fan[4-6] and
pwm[5-6] don't exist.
For the SCH311x and SCH5127, fan[1-3] and pwm[1-3] are always present and
fan[4-6] and pwm[5-6] don't exist.
The hardware monitoring features of the DME1737, A8000, and SCH5027 are only
accessible via SMBus, while the SCH311x only provides access via the ISA bus.
The driver will therefore register itself as an I2C client driver if it detects
a DME1737, A8000, or SCH5027 and as a platform driver if it detects a SCH311x
chip.
accessible via SMBus, while the SCH311x and SCH5127 only provide access via
the ISA bus. The driver will therefore register itself as an I2C client driver
if it detects a DME1737, A8000, or SCH5027 and as a platform driver if it
detects a SCH311x or SCH5127 chip.
Voltage Monitoring
......@@ -76,7 +80,7 @@ DME1737, A8000:
in6: Vbat (+3.0V) 0V - 4.38V
SCH311x:
in0: +2.5V 0V - 6.64V
in0: +2.5V 0V - 3.32V
in1: Vccp (processor core) 0V - 2V
in2: VCC (internal +3.3V) 0V - 4.38V
in3: +5V 0V - 6.64V
......@@ -93,6 +97,15 @@ SCH5027:
in5: VTR (+3.3V standby) 0V - 4.38V
in6: Vbat (+3.0V) 0V - 4.38V
SCH5127:
in0: +2.5 0V - 3.32V
in1: Vccp (processor core) 0V - 3V
in2: VCC (internal +3.3V) 0V - 4.38V
in3: V2_IN 0V - 1.5V
in4: V1_IN 0V - 1.5V
in5: VTR (+3.3V standby) 0V - 4.38V
in6: Vbat (+3.0V) 0V - 4.38V
Each voltage input has associated min and max limits which trigger an alarm
when crossed.
......@@ -293,3 +306,21 @@ pwm[1-3]_auto_point1_pwm RW Auto PWM pwm point. Auto_point1 is the
pwm[1-3]_auto_point2_pwm RO Auto PWM pwm point. Auto_point2 is the
full-speed duty-cycle which is hard-
wired to 255 (100% duty-cycle).
Chip Differences
----------------
Feature dme1737 sch311x sch5027 sch5127
-------------------------------------------------------
temp[1-3]_offset yes yes
vid yes
zone3 yes yes yes
zone[1-3]_hyst yes yes
pwm min/off yes yes
fan3 opt yes opt yes
pwm3 opt yes opt yes
fan4 opt opt
fan5 opt opt
pwm5 opt opt
fan6 opt opt
pwm6 opt opt
......@@ -7,6 +7,11 @@ Supported chips:
Addresses scanned: I2C 0x4c
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/pf/LM/LM63.html
* National Semiconductor LM64
Prefix: 'lm64'
Addresses scanned: I2C 0x18 and 0x4e
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/pf/LM/LM64.html
Author: Jean Delvare <khali@linux-fr.org>
......@@ -55,3 +60,5 @@ The lm63 driver will not update its values more frequently than every
second; reading them more often will do no harm, but will return 'old'
values.
The LM64 is effectively an LM63 with GPIO lines. The driver does not
support these GPIO lines at present.
......@@ -72,9 +72,7 @@ in6_min_alarm 5v output undervoltage alarm
in7_min_alarm 3v output undervoltage alarm
in8_min_alarm Vee (-12v) output undervoltage alarm
in9_input GPIO #1 voltage data
in10_input GPIO #2 voltage data
in11_input GPIO #3 voltage data
in9_input GPIO voltage data
power1_input 12v power usage (mW)
power2_input 5v power usage (mW)
......
......@@ -80,9 +80,9 @@ All entries (except name) are optional, and should only be created in a
given driver if the chip has the feature.
********
* Name *
********
*********************
* Global attributes *
*********************
name The chip name.
This should be a short, lowercase string, not containing
......@@ -91,6 +91,13 @@ name The chip name.
I2C devices get this attribute created automatically.
RO
update_rate The rate at which the chip will update readings.
Unit: millisecond
RW
Some devices have a variable update rate. This attribute
can be used to change the update rate to the desired
frequency.
************
* Voltages *
......
Kernel driver tmp102
====================
Supported chips:
* Texas Instruments TMP102
Prefix: 'tmp102'
Addresses scanned: none
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp102.html
Author:
Steven King <sfking@fdwdc.com>
Description
-----------
The Texas Instruments TMP102 implements one temperature sensor. Limits can be
set through the Overtemperature Shutdown register and Hysteresis register. The
sensor is accurate to 0.5 degree over the range of -25 to +85 C, and to 1.0
degree from -40 to +125 C. Resolution of the sensor is 0.0625 degree. The
operating temperature has a minimum of -55 C and a maximum of +150 C.
The TMP102 has a programmable update rate that can select between 8, 4, 1, and
0.5 Hz. (Currently the driver only supports the default of 4 Hz).
The driver provides the common sysfs-interface for temperatures (see
Documentation/hwmon/sysfs-interface under Temperatures).
......@@ -1206,6 +1206,15 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
}
EXPORT_SYMBOL(acpi_check_mem_region);
/*
* Let drivers know whether the resource checks are effective
*/
int acpi_resources_are_enforced(void)
{
return acpi_enforce_resources == ENFORCE_RESOURCES_STRICT;
}
EXPORT_SYMBOL(acpi_resources_are_enforced);
/*
* Acquire a spinlock.
*
......
......@@ -447,13 +447,14 @@ config SENSORS_IT87
will be called it87.
config SENSORS_LM63
tristate "National Semiconductor LM63"
tristate "National Semiconductor LM63 and LM64"
depends on I2C
help
If you say yes here you get support for the National Semiconductor
LM63 remote diode digital temperature sensor with integrated fan
control. Such chips are found on the Tyan S4882 (Thunder K8QS Pro)
motherboard, among others.
If you say yes here you get support for the National
Semiconductor LM63 and LM64 remote diode digital temperature
sensors with integrated fan control. Such chips are found
on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
others.
This driver can also be built as a module. If so, the module
will be called lm63.
......@@ -492,7 +493,8 @@ config SENSORS_LM75
- NXP's LM75A
- ST Microelectronics STDS75
- TelCom (now Microchip) TCN75
- Texas Instruments TMP100, TMP101, TMP75, TMP175, TMP275
- Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175,
TMP275
This driver supports driver model based binding through board
specific I2C device tables.
......@@ -749,6 +751,16 @@ config SENSORS_DME1737
This driver can also be built as a module. If so, the module
will be called dme1737.
config SENSORS_EMC1403
tristate "SMSC EMC1403 thermal sensor"
depends on I2C
help
If you say yes here you get support for the SMSC EMC1403
temperature monitoring chip.
Threshold values can be configured using sysfs.
Data from the different diodes are accessible via sysfs.
config SENSORS_SMSC47M1
tristate "SMSC LPC47M10x and compatibles"
help
......@@ -831,6 +843,16 @@ config SENSORS_THMC50
This driver can also be built as a module. If so, the module
will be called thmc50.
config SENSORS_TMP102
tristate "Texas Instruments TMP102"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for Texas Instruments TMP102
sensor chips.
This driver can also be built as a module. If so, the module
will be called tmp102.
config SENSORS_TMP401
tristate "Texas Instruments TMP401 and compatibles"
depends on I2C && EXPERIMENTAL
......
......@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o
obj-$(CONFIG_SENSORS_F75375S) += f75375s.o
......@@ -90,6 +91,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
......
......@@ -36,6 +36,7 @@
#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr))
#define ADM1031_REG_PWM (0x22)
#define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr))
#define ADM1031_REG_FAN_FILTER (0x23)
#define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr))
#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr))
......@@ -61,6 +62,9 @@
#define ADM1031_CONF2_TACH2_ENABLE 0x08
#define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan))
#define ADM1031_UPDATE_RATE_MASK 0x1c
#define ADM1031_UPDATE_RATE_SHIFT 2
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
......@@ -75,6 +79,7 @@ struct adm1031_data {
int chip_type;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
unsigned int update_rate; /* In milliseconds */
/* The chan_select_table contains the possible configurations for
* auto fan control.
*/
......@@ -738,6 +743,57 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
/* Update Rate */
static const unsigned int update_rates[] = {
16000, 8000, 4000, 2000, 1000, 500, 250, 125,
};
static ssize_t show_update_rate(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
return sprintf(buf, "%u\n", data->update_rate);
}
static ssize_t set_update_rate(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
unsigned long val;
int i, err;
u8 reg;
err = strict_strtoul(buf, 10, &val);
if (err)
return err;
/* find the nearest update rate from the table */
for (i = 0; i < ARRAY_SIZE(update_rates) - 1; i++) {
if (val >= update_rates[i])
break;
}
/* if not found, we point to the last entry (lowest update rate) */
/* set the new update rate while preserving other settings */
reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
reg &= ~ADM1031_UPDATE_RATE_MASK;
reg |= i << ADM1031_UPDATE_RATE_SHIFT;
adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
mutex_lock(&data->update_lock);
data->update_rate = update_rates[i];
mutex_unlock(&data->update_lock);
return count;
}
static DEVICE_ATTR(update_rate, S_IRUGO | S_IWUSR, show_update_rate,
set_update_rate);
static struct attribute *adm1031_attributes[] = {
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_div.dev_attr.attr,
......@@ -774,6 +830,7 @@ static struct attribute *adm1031_attributes[] = {
&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
&dev_attr_update_rate.attr,
&dev_attr_alarms.attr,
NULL
......@@ -900,6 +957,7 @@ static void adm1031_init_client(struct i2c_client *client)
{
unsigned int read_val;
unsigned int mask;
int i;
struct adm1031_data *data = i2c_get_clientdata(client);
mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
......@@ -919,18 +977,24 @@ static void adm1031_init_client(struct i2c_client *client)
ADM1031_CONF1_MONITOR_ENABLE);
}
/* Read the chip's update rate */
mask = ADM1031_UPDATE_RATE_MASK;
read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
data->update_rate = update_rates[i];
}
static struct adm1031_data *adm1031_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
unsigned long next_update;
int chan;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
next_update = data->last_updated + msecs_to_jiffies(data->update_rate);
if (time_after(jiffies, next_update) || !data->valid) {
dev_dbg(&client->dev, "Starting adm1031 update\n");
for (chan = 0;
......
This diff is collapsed.
......@@ -1411,6 +1411,13 @@ static int __init atk0110_init(void)
{
int ret;
/* 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");
return -EBUSY;
}
ret = acpi_bus_register_driver(&atk_driver);
if (ret)
pr_info("atk: acpi_bus_register_driver failed: %d\n", ret);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -53,7 +53,7 @@
* Address is fully defined internally and cannot be changed.
*/
static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
/*
* The LM63 registers
......@@ -131,12 +131,15 @@ static struct lm63_data *lm63_update_device(struct device *dev);
static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
static void lm63_init_client(struct i2c_client *client);
enum chips { lm63, lm64 };
/*
* Driver data (common to all clients)
*/
static const struct i2c_device_id lm63_id[] = {
{ "lm63", 0 },
{ "lm63", lm63 },
{ "lm64", lm64 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm63_id);
......@@ -422,6 +425,7 @@ static int lm63_detect(struct i2c_client *new_client,
struct i2c_adapter *adapter = new_client->adapter;
u8 man_id, chip_id, reg_config1, reg_config2;
u8 reg_alert_status, reg_alert_mask;
int address = new_client->addr;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
......@@ -439,7 +443,6 @@ static int lm63_detect(struct i2c_client *new_client,
LM63_REG_ALERT_MASK);
if (man_id != 0x01 /* National Semiconductor */
|| chip_id != 0x41 /* LM63 */
|| (reg_config1 & 0x18) != 0x00
|| (reg_config2 & 0xF8) != 0x00
|| (reg_alert_status & 0x20) != 0x00
......@@ -450,7 +453,12 @@ static int lm63_detect(struct i2c_client *new_client,
return -ENODEV;
}
strlcpy(info->type, "lm63", I2C_NAME_SIZE);
if (chip_id == 0x41 && address == 0x4c)
strlcpy(info->type, "lm63", I2C_NAME_SIZE);
else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e))
strlcpy(info->type, "lm64", I2C_NAME_SIZE);
else
return -ENODEV;
return 0;
}
......
......@@ -46,6 +46,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
tcn75,
tmp100,
tmp101,
tmp105,
tmp175,
tmp275,
tmp75,
......@@ -220,6 +221,7 @@ static const struct i2c_device_id lm75_ids[] = {
{ "tcn75", tcn75, },
{ "tmp100", tmp100, },
{ "tmp101", tmp101, },
{ "tmp105", tmp105, },
{ "tmp175", tmp175, },
{ "tmp275", tmp275, },
{ "tmp75", tmp75, },
......
......@@ -982,7 +982,8 @@ static struct lm90_data *lm90_update_device(struct device *dev)
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10)
|| !data->valid) {
u8 h, l;
dev_dbg(&client->dev, "Updating lm90 data.\n");
......
......@@ -45,9 +45,7 @@ enum ltc4245_cmd {
LTC4245_VEEIN = 0x19,
LTC4245_VEESENSE = 0x1a,
LTC4245_VEEOUT = 0x1b,
LTC4245_GPIOADC1 = 0x1c,
LTC4245_GPIOADC2 = 0x1d,
LTC4245_GPIOADC3 = 0x1e,
LTC4245_GPIOADC = 0x1c,
};
struct ltc4245_data {
......@@ -61,7 +59,7 @@ struct ltc4245_data {
u8 cregs[0x08];
/* Voltage registers */
u8 vregs[0x0f];
u8 vregs[0x0d];
};
static struct ltc4245_data *ltc4245_update_device(struct device *dev)
......@@ -86,7 +84,7 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
data->cregs[i] = val;
}
/* Read voltage registers -- 0x10 to 0x1f */
/* Read voltage registers -- 0x10 to 0x1c */
for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
val = i2c_smbus_read_byte_data(client, i+0x10);
if (unlikely(val < 0))
......@@ -128,9 +126,7 @@ static int ltc4245_get_voltage(struct device *dev, u8 reg)
case LTC4245_VEEOUT:
voltage = regval * -55;
break;
case LTC4245_GPIOADC1:
case LTC4245_GPIOADC2:
case LTC4245_GPIOADC3:
case LTC4245_GPIOADC:
voltage = regval * 10;
break;
default:
......@@ -297,9 +293,7 @@ LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2);
LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2);
/* GPIO voltages */
LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC1);
LTC4245_VOLTAGE(in10_input, LTC4245_GPIOADC2);
LTC4245_VOLTAGE(in11_input, LTC4245_GPIOADC3);
LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC);
/* Power Consumption (virtual) */
LTC4245_POWER(power1_input, LTC4245_12VSENSE);
......@@ -342,8 +336,6 @@ static struct attribute *ltc4245_attributes[] = {
&sensor_dev_attr_in8_min_alarm.dev_attr.attr,
&sensor_dev_attr_in9_input.dev_attr.attr,
&sensor_dev_attr_in10_input.dev_attr.attr,
&sensor_dev_attr_in11_input.dev_attr.attr,
&sensor_dev_attr_power1_input.dev_attr.attr,
&sensor_dev_attr_power2_input.dev_attr.attr,
......
/* Texas Instruments TMP102 SMBus temperature sensor driver
*
* Copyright (C) 2010 Steven King <sfking@fdwdc.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
*/
#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>
#define DRIVER_NAME "tmp102"
#define TMP102_TEMP_REG 0x00
#define TMP102_CONF_REG 0x01
/* note: these bit definitions are byte swapped */
#define TMP102_CONF_SD 0x0100
#define TMP102_CONF_TM 0x0200
#define TMP102_CONF_POL 0x0400
#define TMP102_CONF_F0 0x0800
#define TMP102_CONF_F1 0x1000
#define TMP102_CONF_R0 0x2000
#define TMP102_CONF_R1 0x4000
#define TMP102_CONF_OS 0x8000
#define TMP102_CONF_EM 0x0010
#define TMP102_CONF_AL 0x0020
#define TMP102_CONF_CR0 0x0040
#define TMP102_CONF_CR1 0x0080
#define TMP102_TLOW_REG 0x02
#define TMP102_THIGH_REG 0x03
struct tmp102 {
struct device *hwmon_dev;
struct mutex lock;
u16 config_orig;
unsigned long last_update;
int temp[3];
};
/* SMBus specifies low byte first, but the TMP102 returns high byte first,
* so we have to swab16 the values */
static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
{
int result = i2c_smbus_read_word_data(client, reg);
return result < 0 ? result : swab16(result);
}
static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
{
return i2c_smbus_write_word_data(client, reg, swab16(val));
}
/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
static inline int tmp102_reg_to_mC(s16 val)
{
return ((val & ~0x01) * 1000) / 128;
}
/* convert milliCelsius to left adjusted 13-bit TMP102 register value */
static inline u16 tmp102_mC_to_reg(int val)
{
return (val * 128) / 1000;
}
static const u8 tmp102_reg[] = {
TMP102_TEMP_REG,
TMP102_TLOW_REG,
TMP102_THIGH_REG,
};
static struct tmp102 *tmp102_update_device(struct i2c_client *client)
{
struct tmp102 *tmp102 = i2c_get_clientdata(client);
mutex_lock(&tmp102->lock);
if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
int i;
for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
int status = tmp102_read_reg(client, tmp102_reg[i]);
if (status > -1)
tmp102->temp[i] = tmp102_reg_to_mC(status);
}
tmp102->last_update = jiffies;
}
mutex_unlock(&tmp102->lock);
return tmp102;
}
static ssize_t tmp102_show_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
}
static ssize_t tmp102_set_temp(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
struct i2c_client *client = to_i2c_client(dev);
struct tmp102 *tmp102 = i2c_get_clientdata(client);
long val;
int status;
if (strict_strtol(buf, 10, &val) < 0)
return -EINVAL;
val = SENSORS_LIMIT(val, -256000, 255000);
mutex_lock(&tmp102->lock);
tmp102->temp[sda->index] = val;
status = tmp102_write_reg(client, tmp102_reg[sda->index],
tmp102_mC_to_reg(val));
mutex_unlock(&tmp102->lock);
return status ? : count;
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0);
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
tmp102_set_temp, 1);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
tmp102_set_temp, 2);
static struct attribute *tmp102_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
NULL
};
static const struct attribute_group tmp102_attr_group = {
.attrs = tmp102_attributes,
};
#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
static int __devinit tmp102_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tmp102 *tmp102;
int status;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA)) {
dev_err(&client->dev, "adapter doesnt support SMBus word "
"transactions\n");
return -ENODEV;
}
tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL);
if (!tmp102) {
dev_dbg(&client->dev, "kzalloc failed\n");
return -ENOMEM;
}
i2c_set_clientdata(client, tmp102);
status = tmp102_read_reg(client, TMP102_CONF_REG);
if (status < 0) {
dev_err(&client->dev, "error reading config register\n");
goto fail_free;
}
tmp102->config_orig = status;
status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
if (status < 0) {
dev_err(&client->dev, "error writing config register\n");
goto fail_restore_config;
}
status = tmp102_read_reg(client, TMP102_CONF_REG);
if (status < 0) {
dev_err(&client->dev, "error reading config register\n");
goto fail_restore_config;
}
status &= ~TMP102_CONFIG_RD_ONLY;
if (status != TMP102_CONFIG) {
dev_err(&client->dev, "config settings did not stick\n");
status = -ENODEV;
goto fail_restore_config;
}
tmp102->last_update = jiffies - HZ;
mutex_init(&tmp102->lock);
status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group);
if (status) {
dev_dbg(&client->dev, "could not create sysfs files\n");
goto fail_restore_config;
}
tmp102->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(tmp102->hwmon_dev)) {
dev_dbg(&client->dev, "unable to register hwmon device\n");
status = PTR_ERR(tmp102->hwmon_dev);
goto fail_remove_sysfs;
}
dev_info(&client->dev, "initialized\n");
return 0;
fail_remove_sysfs:
sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
fail_restore_config:
tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
fail_free:
i2c_set_clientdata(client, NULL);
kfree(tmp102);
return status;
}
static int __devexit tmp102_remove(struct i2c_client *client)
{
struct tmp102 *tmp102 = i2c_get_clientdata(client);
hwmon_device_unregister(tmp102->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
/* Stop monitoring if device was stopped originally */
if (tmp102->config_orig & TMP102_CONF_SD) {
int config;
config = tmp102_read_reg(client, TMP102_CONF_REG);
if (config >= 0)
tmp102_write_reg(client, TMP102_CONF_REG,
config | TMP102_CONF_SD);
}
i2c_set_clientdata(client, NULL);
kfree(tmp102);
return 0;
}
#ifdef CONFIG_PM
static int tmp102_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
int config;
config = tmp102_read_reg(client, TMP102_CONF_REG);
if (config < 0)
return config;
config |= TMP102_CONF_SD;
return tmp102_write_reg(client, TMP102_CONF_REG, config);
}
static int tmp102_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
int config;
config = tmp102_read_reg(client, TMP102_CONF_REG);
if (config < 0)
return config;
config &= ~TMP102_CONF_SD;
return tmp102_write_reg(client, TMP102_CONF_REG, config);
}
static const struct dev_pm_ops tmp102_dev_pm_ops = {
.suspend = tmp102_suspend,
.resume = tmp102_resume,
};
#define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops)
#else
#define TMP102_DEV_PM_OPS NULL
#endif /* CONFIG_PM */
static const struct i2c_device_id tmp102_id[] = {
{ "tmp102", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tmp102_id);
static struct i2c_driver tmp102_driver = {
.driver.name = DRIVER_NAME,
.driver.pm = TMP102_DEV_PM_OPS,
.probe = tmp102_probe,
.remove = __devexit_p(tmp102_remove),
.id_table = tmp102_id,
};
static int __init tmp102_init(void)
{
return i2c_add_driver(&tmp102_driver);
}
module_init(tmp102_init);
static void __exit tmp102_exit(void)
{
i2c_del_driver(&tmp102_driver);
}
module_exit(tmp102_exit);
MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -248,6 +248,8 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
int acpi_check_mem_region(resource_size_t start, resource_size_t n,
const char *name);
int acpi_resources_are_enforced(void);
#ifdef CONFIG_PM_SLEEP
void __init acpi_no_s4_hw_signature(void);
void __init acpi_old_suspend_ordering(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment