aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ds1621.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/hwmon/ds1621.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/hwmon/ds1621.c')
-rw-r--r--drivers/hwmon/ds1621.c129
1 files changed, 78 insertions, 51 deletions
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 1c568736baf..e11363467a8 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -1,25 +1,25 @@
1/* 1/*
2 * ds1621.c - Part of lm_sensors, Linux kernel modules for hardware 2 ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
3 * monitoring 3 monitoring
4 * Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23 4 Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23
5 * based on lm75.c by Frodo Looijaard <frodol@dds.nl> 5 based on lm75.c by Frodo Looijaard <frodol@dds.nl>
6 * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with 6 Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
7 * the help of Jean Delvare <khali@linux-fr.org> 7 the help of Jean Delvare <khali@linux-fr.org>
8 * 8
9 * This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or 11 the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version. 12 (at your option) any later version.
13 * 13
14 * This program is distributed in the hope that it will be useful, 14 This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details. 17 GNU General Public License for more details.
18 * 18
19 * You should have received a copy of the GNU General Public License 19 You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software 20 along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */ 22*/
23 23
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/init.h> 25#include <linux/init.h>
@@ -67,7 +67,7 @@ static const u8 DS1621_REG_TEMP[3] = {
67 67
68/* Conversions */ 68/* Conversions */
69#define ALARMS_FROM_REG(val) ((val) & \ 69#define ALARMS_FROM_REG(val) ((val) & \
70 (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW)) 70 (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
71 71
72/* Each client has this additional data */ 72/* Each client has this additional data */
73struct ds1621_data { 73struct ds1621_data {
@@ -80,6 +80,24 @@ struct ds1621_data {
80 u8 conf; /* Register encoding, combined */ 80 u8 conf; /* Register encoding, combined */
81}; 81};
82 82
83/* Temperature registers are word-sized.
84 DS1621 uses a high-byte first convention, which is exactly opposite to
85 the SMBus standard. */
86static int ds1621_read_temp(struct i2c_client *client, u8 reg)
87{
88 int ret;
89
90 ret = i2c_smbus_read_word_data(client, reg);
91 if (ret < 0)
92 return ret;
93 return swab16(ret);
94}
95
96static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value)
97{
98 return i2c_smbus_write_word_data(client, reg, swab16(value));
99}
100
83static void ds1621_init_client(struct i2c_client *client) 101static void ds1621_init_client(struct i2c_client *client)
84{ 102{
85 u8 conf, new_conf; 103 u8 conf, new_conf;
@@ -93,10 +111,10 @@ static void ds1621_init_client(struct i2c_client *client)
93 new_conf &= ~DS1621_REG_CONFIG_POLARITY; 111 new_conf &= ~DS1621_REG_CONFIG_POLARITY;
94 else if (polarity == 1) 112 else if (polarity == 1)
95 new_conf |= DS1621_REG_CONFIG_POLARITY; 113 new_conf |= DS1621_REG_CONFIG_POLARITY;
96 114
97 if (conf != new_conf) 115 if (conf != new_conf)
98 i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); 116 i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf);
99 117
100 /* start conversion */ 118 /* start conversion */
101 i2c_smbus_write_byte(client, DS1621_COM_START); 119 i2c_smbus_write_byte(client, DS1621_COM_START);
102} 120}
@@ -118,7 +136,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
118 data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); 136 data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
119 137
120 for (i = 0; i < ARRAY_SIZE(data->temp); i++) 138 for (i = 0; i < ARRAY_SIZE(data->temp); i++)
121 data->temp[i] = i2c_smbus_read_word_swapped(client, 139 data->temp[i] = ds1621_read_temp(client,
122 DS1621_REG_TEMP[i]); 140 DS1621_REG_TEMP[i]);
123 141
124 /* reset alarms if necessary */ 142 /* reset alarms if necessary */
@@ -155,17 +173,12 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
155 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 173 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
156 struct i2c_client *client = to_i2c_client(dev); 174 struct i2c_client *client = to_i2c_client(dev);
157 struct ds1621_data *data = i2c_get_clientdata(client); 175 struct ds1621_data *data = i2c_get_clientdata(client);
158 long val; 176 u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10));
159 int err;
160
161 err = kstrtol(buf, 10, &val);
162 if (err)
163 return err;
164 177
165 mutex_lock(&data->update_lock); 178 mutex_lock(&data->update_lock);
166 data->temp[attr->index] = LM75_TEMP_TO_REG(val); 179 data->temp[attr->index] = val;
167 i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index], 180 ds1621_write_temp(client, DS1621_REG_TEMP[attr->index],
168 data->temp[attr->index]); 181 data->temp[attr->index]);
169 mutex_unlock(&data->update_lock); 182 mutex_unlock(&data->update_lock);
170 return count; 183 return count;
171} 184}
@@ -217,17 +230,14 @@ static int ds1621_detect(struct i2c_client *client,
217 int conf, temp; 230 int conf, temp;
218 int i; 231 int i;
219 232
220 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 233 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
221 | I2C_FUNC_SMBUS_WORD_DATA 234 | I2C_FUNC_SMBUS_WORD_DATA
222 | I2C_FUNC_SMBUS_WRITE_BYTE)) 235 | I2C_FUNC_SMBUS_WRITE_BYTE))
223 return -ENODEV; 236 return -ENODEV;
224 237
225 /* 238 /* Now, we do the remaining detection. It is lousy. */
226 * Now, we do the remaining detection. It is lousy. 239 /* The NVB bit should be low if no EEPROM write has been requested
227 * 240 during the latest 10ms, which is highly improbable in our case. */
228 * The NVB bit should be low if no EEPROM write has been requested
229 * during the latest 10ms, which is highly improbable in our case.
230 */
231 conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); 241 conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
232 if (conf < 0 || conf & DS1621_REG_CONFIG_NVB) 242 if (conf < 0 || conf & DS1621_REG_CONFIG_NVB)
233 return -ENODEV; 243 return -ENODEV;
@@ -249,10 +259,11 @@ static int ds1621_probe(struct i2c_client *client,
249 struct ds1621_data *data; 259 struct ds1621_data *data;
250 int err; 260 int err;
251 261
252 data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data), 262 data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL);
253 GFP_KERNEL); 263 if (!data) {
254 if (!data) 264 err = -ENOMEM;
255 return -ENOMEM; 265 goto exit;
266 }
256 267
257 i2c_set_clientdata(client, data); 268 i2c_set_clientdata(client, data);
258 mutex_init(&data->update_lock); 269 mutex_init(&data->update_lock);
@@ -261,9 +272,8 @@ static int ds1621_probe(struct i2c_client *client,
261 ds1621_init_client(client); 272 ds1621_init_client(client);
262 273
263 /* Register sysfs hooks */ 274 /* Register sysfs hooks */
264 err = sysfs_create_group(&client->dev.kobj, &ds1621_group); 275 if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
265 if (err) 276 goto exit_free;
266 return err;
267 277
268 data->hwmon_dev = hwmon_device_register(&client->dev); 278 data->hwmon_dev = hwmon_device_register(&client->dev);
269 if (IS_ERR(data->hwmon_dev)) { 279 if (IS_ERR(data->hwmon_dev)) {
@@ -273,8 +283,11 @@ static int ds1621_probe(struct i2c_client *client,
273 283
274 return 0; 284 return 0;
275 285
276 exit_remove_files: 286 exit_remove_files:
277 sysfs_remove_group(&client->dev.kobj, &ds1621_group); 287 sysfs_remove_group(&client->dev.kobj, &ds1621_group);
288 exit_free:
289 kfree(data);
290 exit:
278 return err; 291 return err;
279} 292}
280 293
@@ -285,6 +298,8 @@ static int ds1621_remove(struct i2c_client *client)
285 hwmon_device_unregister(data->hwmon_dev); 298 hwmon_device_unregister(data->hwmon_dev);
286 sysfs_remove_group(&client->dev.kobj, &ds1621_group); 299 sysfs_remove_group(&client->dev.kobj, &ds1621_group);
287 300
301 kfree(data);
302
288 return 0; 303 return 0;
289} 304}
290 305
@@ -308,8 +323,20 @@ static struct i2c_driver ds1621_driver = {
308 .address_list = normal_i2c, 323 .address_list = normal_i2c,
309}; 324};
310 325
311module_i2c_driver(ds1621_driver); 326static int __init ds1621_init(void)
327{
328 return i2c_add_driver(&ds1621_driver);
329}
330
331static void __exit ds1621_exit(void)
332{
333 i2c_del_driver(&ds1621_driver);
334}
335
312 336
313MODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>"); 337MODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>");
314MODULE_DESCRIPTION("DS1621 driver"); 338MODULE_DESCRIPTION("DS1621 driver");
315MODULE_LICENSE("GPL"); 339MODULE_LICENSE("GPL");
340
341module_init(ds1621_init);
342module_exit(ds1621_exit);