Skip to content

Commit

Permalink
hwmon: (lm95234) Add support for LM95233
Browse files Browse the repository at this point in the history
LM95233 is similar to LM95234, but it only supports two
instead of four external temperature sensors.

Reviewed-by: Jean Delvare <[email protected]>
Signed-off-by: Guenter Roeck <[email protected]>
  • Loading branch information
groeck committed Dec 2, 2014
1 parent 162a8df commit dfcd4c5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 34 deletions.
15 changes: 10 additions & 5 deletions Documentation/hwmon/lm95234
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ Kernel driver lm95234
=====================

Supported chips:
* National Semiconductor / Texas Instruments LM95233
Addresses scanned: I2C 0x18, 0x2a, 0x2b
Datasheet: Publicly available at the Texas Instruments website
http://www.ti.com/product/lm95233
* National Semiconductor / Texas Instruments LM95234
Addresses scanned: I2C 0x18, 0x4d, 0x4e
Datasheet: Publicly available at the Texas Instruments website
Expand All @@ -13,11 +17,12 @@ Author: Guenter Roeck <[email protected]>
Description
-----------

LM95234 is an 11-bit digital temperature sensor with a 2-wire System Management
Bus (SMBus) interface and TrueTherm technology that can very accurately monitor
the temperature of four remote diodes as well as its own temperature.
The four remote diodes can be external devices such as microprocessors,
graphics processors or diode-connected 2N3904s. The LM95234's TruTherm
LM95233 and LM95234 are 11-bit digital temperature sensors with a 2-wire
System Management Bus (SMBus) interface and TrueTherm technology
that can very accurately monitor the temperature of two (LM95233)
or four (LM95234) remote diodes as well as its own temperature.
The remote diodes can be external devices such as microprocessors,
graphics processors or diode-connected 2N3904s. The chip's TruTherm
beta compensation technology allows sensing of 90 nm or 65 nm process
thermal diodes accurately.

Expand Down
6 changes: 3 additions & 3 deletions drivers/hwmon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1028,11 +1028,11 @@ config SENSORS_LM93
will be called lm93.

config SENSORS_LM95234
tristate "National Semiconductor LM95234"
tristate "National Semiconductor LM95234 and compatibles"
depends on I2C
help
If you say yes here you get support for the LM95234 temperature
sensor.
If you say yes here you get support for the LM95233 and LM95234
temperature sensor chips.

This driver can also be built as a module. If so, the module
will be called lm95234.
Expand Down
91 changes: 65 additions & 26 deletions drivers/hwmon/lm95234.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Driver for Texas Instruments / National Semiconductor LM95234
*
* Copyright (c) 2013 Guenter Roeck <[email protected]>
* Copyright (c) 2013, 2014 Guenter Roeck <[email protected]>
*
* Derived from lm95241.c
* Copyright (C) 2008, 2010 Davide Rizzo <[email protected]>
Expand Down Expand Up @@ -30,7 +30,10 @@

#define DRVNAME "lm95234"

static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
enum chips { lm95233, lm95234 };

static const unsigned short normal_i2c[] = {
0x18, 0x2a, 0x2b, 0x4d, 0x4e, I2C_CLIENT_END };

/* LM95234 registers */
#define LM95234_REG_MAN_ID 0xFE
Expand All @@ -53,11 +56,13 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
#define LM95234_REG_TCRIT_HYST 0x5a

#define NATSEMI_MAN_ID 0x01
#define LM95233_CHIP_ID 0x89
#define LM95234_CHIP_ID 0x79

/* Client data (each client gets its own) */
struct lm95234_data {
struct i2c_client *client;
const struct attribute_group *groups[3];
struct mutex update_lock;
unsigned long last_updated, interval; /* in jiffies */
bool valid; /* false until following fields are valid */
Expand Down Expand Up @@ -564,35 +569,23 @@ static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
set_interval);

static struct attribute *lm95234_attrs[] = {
static struct attribute *lm95234_common_attrs[] = {
&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_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
&sensor_dev_attr_temp2_type.dev_attr.attr,
&sensor_dev_attr_temp3_type.dev_attr.attr,
&sensor_dev_attr_temp4_type.dev_attr.attr,
&sensor_dev_attr_temp5_type.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
Expand All @@ -601,18 +594,44 @@ static struct attribute *lm95234_attrs[] = {
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_offset.dev_attr.attr,
&sensor_dev_attr_temp3_offset.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL
};

static const struct attribute_group lm95234_common_group = {
.attrs = lm95234_common_attrs,
};

static struct attribute *lm95234_attrs[] = {
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
&sensor_dev_attr_temp4_type.dev_attr.attr,
&sensor_dev_attr_temp5_type.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_offset.dev_attr.attr,
&sensor_dev_attr_temp5_offset.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL
};
ATTRIBUTE_GROUPS(lm95234);

static const struct attribute_group lm95234_group = {
.attrs = lm95234_attrs,
};

static int lm95234_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
int address = client->addr;
u8 config_mask, model_mask;
int mfg_id, chip_id, val;
const char *name;

if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
Expand All @@ -622,30 +641,46 @@ static int lm95234_detect(struct i2c_client *client,
return -ENODEV;

chip_id = i2c_smbus_read_byte_data(client, LM95234_REG_CHIP_ID);
if (chip_id != LM95234_CHIP_ID)
switch (chip_id) {
case LM95233_CHIP_ID:
if (address != 0x18 && address != 0x2a && address != 0x2b)
return -ENODEV;
config_mask = 0xbf;
model_mask = 0xf9;
name = "lm95233";
break;
case LM95234_CHIP_ID:
if (address != 0x18 && address != 0x4d && address != 0x4e)
return -ENODEV;
config_mask = 0xbc;
model_mask = 0xe1;
name = "lm95234";
break;
default:
return -ENODEV;
}

val = i2c_smbus_read_byte_data(client, LM95234_REG_STATUS);
if (val & 0x30)
return -ENODEV;

val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
if (val & 0xbc)
if (val & config_mask)
return -ENODEV;

val = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
if (val & 0xfc)
return -ENODEV;

val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
if (val & 0xe1)
if (val & model_mask)
return -ENODEV;

val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
if (val & 0xe1)
if (val & model_mask)
return -ENODEV;

strlcpy(info->type, "lm95234", I2C_NAME_SIZE);
strlcpy(info->type, name, I2C_NAME_SIZE);
return 0;
}

Expand Down Expand Up @@ -698,15 +733,19 @@ static int lm95234_probe(struct i2c_client *client,
if (err < 0)
return err;

data->groups[0] = &lm95234_common_group;
if (id->driver_data == lm95234)
data->groups[1] = &lm95234_group;

hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
data,
lm95234_groups);
data, data->groups);
return PTR_ERR_OR_ZERO(hwmon_dev);
}

/* Driver data (common to all clients) */
static const struct i2c_device_id lm95234_id[] = {
{ "lm95234", 0 },
{ "lm95233", lm95233 },
{ "lm95234", lm95234 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm95234_id);
Expand All @@ -725,5 +764,5 @@ static struct i2c_driver lm95234_driver = {
module_i2c_driver(lm95234_driver);

MODULE_AUTHOR("Guenter Roeck <[email protected]>");
MODULE_DESCRIPTION("LM95234 sensor driver");
MODULE_DESCRIPTION("LM95233/LM95234 sensor driver");
MODULE_LICENSE("GPL");

0 comments on commit dfcd4c5

Please sign in to comment.