aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/shtc143
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/atxp1.c42
-rw-r--r--drivers/hwmon/ina2xx.c7
-rw-r--r--drivers/hwmon/lm85.c33
-rw-r--r--drivers/hwmon/ltc4151.c51
-rw-r--r--drivers/hwmon/shtc1.c251
-rw-r--r--drivers/hwmon/vexpress.c82
-rw-r--r--include/linux/platform_data/shtc1.h23
10 files changed, 401 insertions, 142 deletions
diff --git a/Documentation/hwmon/shtc1 b/Documentation/hwmon/shtc1
new file mode 100644
index 000000000000..6b1e05458f0f
--- /dev/null
+++ b/Documentation/hwmon/shtc1
@@ -0,0 +1,43 @@
1Kernel driver shtc1
2===================
3
4Supported chips:
5 * Sensirion SHTC1
6 Prefix: 'shtc1'
7 Addresses scanned: none
8 Datasheet: http://www.sensirion.com/file/datasheet_shtc1
9
10 * Sensirion SHTW1
11 Prefix: 'shtw1'
12 Addresses scanned: none
13 Datasheet: Not publicly available
14
15Author:
16 Johannes Winkelmann <johannes.winkelmann@sensirion.com>
17
18Description
19-----------
20
21This driver implements support for the Sensirion SHTC1 chip, a humidity and
22temperature sensor. Temperature is measured in degrees celsius, relative
23humidity is expressed as a percentage. Driver can be used as well for SHTW1
24chip, which has the same electrical interface.
25
26The device communicates with the I2C protocol. All sensors are set to I2C
27address 0x70. See Documentation/i2c/instantiating-devices for methods to
28instantiate the device.
29
30There are two options configurable by means of shtc1_platform_data:
311. blocking (pull the I2C clock line down while performing the measurement) or
32 non-blocking mode. Blocking mode will guarantee the fastest result but
33 the I2C bus will be busy during that time. By default, non-blocking mode
34 is used. Make sure clock-stretching works properly on your device if you
35 want to use blocking mode.
362. high or low accuracy. High accuracy is used by default and using it is
37 strongly recommended.
38
39sysfs-Interface
40---------------
41
42temp1_input - temperature input
43humidity1_input - humidity input
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 00343166feb1..08531a128f53 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1124,6 +1124,16 @@ config SENSORS_SHT21
1124 This driver can also be built as a module. If so, the module 1124 This driver can also be built as a module. If so, the module
1125 will be called sht21. 1125 will be called sht21.
1126 1126
1127config SENSORS_SHTC1
1128 tristate "Sensiron humidity and temperature sensors. SHTC1 and compat."
1129 depends on I2C
1130 help
1131 If you say yes here you get support for the Sensiron SHTC1 and SHTW1
1132 humidity and temperature sensors.
1133
1134 This driver can also be built as a module. If so, the module
1135 will be called shtc1.
1136
1127config SENSORS_S3C 1137config SENSORS_S3C
1128 tristate "Samsung built-in ADC" 1138 tristate "Samsung built-in ADC"
1129 depends on S3C_ADC 1139 depends on S3C_ADC
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 11798ad7e801..3dc0f02f71d2 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
126obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o 126obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o
127obj-$(CONFIG_SENSORS_SHT15) += sht15.o 127obj-$(CONFIG_SENSORS_SHT15) += sht15.o
128obj-$(CONFIG_SENSORS_SHT21) += sht21.o 128obj-$(CONFIG_SENSORS_SHT21) += sht21.o
129obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
129obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o 130obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
130obj-$(CONFIG_SENSORS_SMM665) += smm665.o 131obj-$(CONFIG_SENSORS_SMM665) += smm665.o
131obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o 132obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 6edce42c61d5..2ae8a304b5ef 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -45,30 +45,6 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
45 45
46static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; 46static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
47 47
48static int atxp1_probe(struct i2c_client *client,
49 const struct i2c_device_id *id);
50static int atxp1_remove(struct i2c_client *client);
51static struct atxp1_data *atxp1_update_device(struct device *dev);
52static int atxp1_detect(struct i2c_client *client, struct i2c_board_info *info);
53
54static const struct i2c_device_id atxp1_id[] = {
55 { "atxp1", 0 },
56 { }
57};
58MODULE_DEVICE_TABLE(i2c, atxp1_id);
59
60static struct i2c_driver atxp1_driver = {
61 .class = I2C_CLASS_HWMON,
62 .driver = {
63 .name = "atxp1",
64 },
65 .probe = atxp1_probe,
66 .remove = atxp1_remove,
67 .id_table = atxp1_id,
68 .detect = atxp1_detect,
69 .address_list = normal_i2c,
70};
71
72struct atxp1_data { 48struct atxp1_data {
73 struct device *hwmon_dev; 49 struct device *hwmon_dev;
74 struct mutex update_lock; 50 struct mutex update_lock;
@@ -386,4 +362,22 @@ static int atxp1_remove(struct i2c_client *client)
386 return 0; 362 return 0;
387}; 363};
388 364
365static const struct i2c_device_id atxp1_id[] = {
366 { "atxp1", 0 },
367 { }
368};
369MODULE_DEVICE_TABLE(i2c, atxp1_id);
370
371static struct i2c_driver atxp1_driver = {
372 .class = I2C_CLASS_HWMON,
373 .driver = {
374 .name = "atxp1",
375 },
376 .probe = atxp1_probe,
377 .remove = atxp1_remove,
378 .id_table = atxp1_id,
379 .detect = atxp1_detect,
380 .address_list = normal_i2c,
381};
382
389module_i2c_driver(atxp1_driver); 383module_i2c_driver(atxp1_driver);
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 93d26e8af3e2..bfd3f3eeabcd 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -148,7 +148,8 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg)
148 148
149 switch (reg) { 149 switch (reg) {
150 case INA2XX_SHUNT_VOLTAGE: 150 case INA2XX_SHUNT_VOLTAGE:
151 val = DIV_ROUND_CLOSEST(data->regs[reg], 151 /* signed register */
152 val = DIV_ROUND_CLOSEST((s16)data->regs[reg],
152 data->config->shunt_div); 153 data->config->shunt_div);
153 break; 154 break;
154 case INA2XX_BUS_VOLTAGE: 155 case INA2XX_BUS_VOLTAGE:
@@ -160,8 +161,8 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg)
160 val = data->regs[reg] * data->config->power_lsb; 161 val = data->regs[reg] * data->config->power_lsb;
161 break; 162 break;
162 case INA2XX_CURRENT: 163 case INA2XX_CURRENT:
163 /* LSB=1mA (selected). Is in mA */ 164 /* signed register, LSB=1mA (selected), in mA */
164 val = data->regs[reg]; 165 val = (s16)data->regs[reg];
165 break; 166 break;
166 default: 167 default:
167 /* programmer goofed */ 168 /* programmer goofed */
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index bed4af358308..b0129a54e1a6 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -5,7 +5,7 @@
5 * Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> 5 * Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
6 * Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de> 6 * Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
7 * Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com> 7 * Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
8 * Copyright (C) 2007--2009 Jean Delvare <jdelvare@suse.de> 8 * Copyright (C) 2007--2014 Jean Delvare <jdelvare@suse.de>
9 * 9 *
10 * Chip details at <http://www.national.com/ds/LM/LM85.pdf> 10 * Chip details at <http://www.national.com/ds/LM/LM85.pdf>
11 * 11 *
@@ -39,7 +39,7 @@
39static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 39static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
40 40
41enum chips { 41enum chips {
42 any_chip, lm85b, lm85c, 42 lm85,
43 adm1027, adt7463, adt7468, 43 adm1027, adt7463, adt7468,
44 emc6d100, emc6d102, emc6d103, emc6d103s 44 emc6d100, emc6d102, emc6d103, emc6d103s
45}; 45};
@@ -75,9 +75,6 @@ enum chips {
75#define LM85_COMPANY_NATIONAL 0x01 75#define LM85_COMPANY_NATIONAL 0x01
76#define LM85_COMPANY_ANALOG_DEV 0x41 76#define LM85_COMPANY_ANALOG_DEV 0x41
77#define LM85_COMPANY_SMSC 0x5c 77#define LM85_COMPANY_SMSC 0x5c
78#define LM85_VERSTEP_VMASK 0xf0
79#define LM85_VERSTEP_GENERIC 0x60
80#define LM85_VERSTEP_GENERIC2 0x70
81#define LM85_VERSTEP_LM85C 0x60 78#define LM85_VERSTEP_LM85C 0x60
82#define LM85_VERSTEP_LM85B 0x62 79#define LM85_VERSTEP_LM85B 0x62
83#define LM85_VERSTEP_LM96000_1 0x68 80#define LM85_VERSTEP_LM96000_1 0x68
@@ -351,9 +348,9 @@ static const struct i2c_device_id lm85_id[] = {
351 { "adm1027", adm1027 }, 348 { "adm1027", adm1027 },
352 { "adt7463", adt7463 }, 349 { "adt7463", adt7463 },
353 { "adt7468", adt7468 }, 350 { "adt7468", adt7468 },
354 { "lm85", any_chip }, 351 { "lm85", lm85 },
355 { "lm85b", lm85b }, 352 { "lm85b", lm85 },
356 { "lm85c", lm85c }, 353 { "lm85c", lm85 },
357 { "emc6d100", emc6d100 }, 354 { "emc6d100", emc6d100 },
358 { "emc6d101", emc6d100 }, 355 { "emc6d101", emc6d100 },
359 { "emc6d102", emc6d102 }, 356 { "emc6d102", emc6d102 },
@@ -1281,7 +1278,7 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
1281{ 1278{
1282 struct i2c_adapter *adapter = client->adapter; 1279 struct i2c_adapter *adapter = client->adapter;
1283 int address = client->addr; 1280 int address = client->addr;
1284 const char *type_name; 1281 const char *type_name = NULL;
1285 int company, verstep; 1282 int company, verstep;
1286 1283
1287 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 1284 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -1297,16 +1294,6 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
1297 "Detecting device at 0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n", 1294 "Detecting device at 0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
1298 address, company, verstep); 1295 address, company, verstep);
1299 1296
1300 /* All supported chips have the version in common */
1301 if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC &&
1302 (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) {
1303 dev_dbg(&adapter->dev,
1304 "Autodetection failed: unsupported version\n");
1305 return -ENODEV;
1306 }
1307 type_name = "lm85";
1308
1309 /* Now, refine the detection */
1310 if (company == LM85_COMPANY_NATIONAL) { 1297 if (company == LM85_COMPANY_NATIONAL) {
1311 switch (verstep) { 1298 switch (verstep) {
1312 case LM85_VERSTEP_LM85C: 1299 case LM85_VERSTEP_LM85C:
@@ -1323,6 +1310,7 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
1323 "Found Winbond WPCD377I, ignoring\n"); 1310 "Found Winbond WPCD377I, ignoring\n");
1324 return -ENODEV; 1311 return -ENODEV;
1325 } 1312 }
1313 type_name = "lm85";
1326 break; 1314 break;
1327 } 1315 }
1328 } else if (company == LM85_COMPANY_ANALOG_DEV) { 1316 } else if (company == LM85_COMPANY_ANALOG_DEV) {
@@ -1357,12 +1345,11 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
1357 type_name = "emc6d103s"; 1345 type_name = "emc6d103s";
1358 break; 1346 break;
1359 } 1347 }
1360 } else {
1361 dev_dbg(&adapter->dev,
1362 "Autodetection failed: unknown vendor\n");
1363 return -ENODEV;
1364 } 1348 }
1365 1349
1350 if (!type_name)
1351 return -ENODEV;
1352
1366 strlcpy(info->type, type_name, I2C_NAME_SIZE); 1353 strlcpy(info->type, type_name, I2C_NAME_SIZE);
1367 1354
1368 return 0; 1355 return 0;
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
index af81be1237c9..c86a18402496 100644
--- a/drivers/hwmon/ltc4151.c
+++ b/drivers/hwmon/ltc4151.c
@@ -47,7 +47,7 @@
47#define LTC4151_ADIN_L 0x05 47#define LTC4151_ADIN_L 0x05
48 48
49struct ltc4151_data { 49struct ltc4151_data {
50 struct device *hwmon_dev; 50 struct i2c_client *client;
51 51
52 struct mutex update_lock; 52 struct mutex update_lock;
53 bool valid; 53 bool valid;
@@ -59,8 +59,8 @@ struct ltc4151_data {
59 59
60static struct ltc4151_data *ltc4151_update_device(struct device *dev) 60static struct ltc4151_data *ltc4151_update_device(struct device *dev)
61{ 61{
62 struct i2c_client *client = to_i2c_client(dev); 62 struct ltc4151_data *data = dev_get_drvdata(dev);
63 struct ltc4151_data *data = i2c_get_clientdata(client); 63 struct i2c_client *client = data->client;
64 struct ltc4151_data *ret = data; 64 struct ltc4151_data *ret = data;
65 65
66 mutex_lock(&data->update_lock); 66 mutex_lock(&data->update_lock);
@@ -159,7 +159,7 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4151_show_value, NULL,
159 * Finally, construct an array of pointers to members of the above objects, 159 * Finally, construct an array of pointers to members of the above objects,
160 * as required for sysfs_create_group() 160 * as required for sysfs_create_group()
161 */ 161 */
162static struct attribute *ltc4151_attributes[] = { 162static struct attribute *ltc4151_attrs[] = {
163 &sensor_dev_attr_in1_input.dev_attr.attr, 163 &sensor_dev_attr_in1_input.dev_attr.attr,
164 &sensor_dev_attr_in2_input.dev_attr.attr, 164 &sensor_dev_attr_in2_input.dev_attr.attr,
165 165
@@ -167,54 +167,30 @@ static struct attribute *ltc4151_attributes[] = {
167 167
168 NULL, 168 NULL,
169}; 169};
170 170ATTRIBUTE_GROUPS(ltc4151);
171static const struct attribute_group ltc4151_group = {
172 .attrs = ltc4151_attributes,
173};
174 171
175static int ltc4151_probe(struct i2c_client *client, 172static int ltc4151_probe(struct i2c_client *client,
176 const struct i2c_device_id *id) 173 const struct i2c_device_id *id)
177{ 174{
178 struct i2c_adapter *adapter = client->adapter; 175 struct i2c_adapter *adapter = client->adapter;
176 struct device *dev = &client->dev;
179 struct ltc4151_data *data; 177 struct ltc4151_data *data;
180 int ret; 178 struct device *hwmon_dev;
181 179
182 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 180 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
183 return -ENODEV; 181 return -ENODEV;
184 182
185 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 183 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
186 if (!data) 184 if (!data)
187 return -ENOMEM; 185 return -ENOMEM;
188 186
189 i2c_set_clientdata(client, data); 187 data->client = client;
190 mutex_init(&data->update_lock); 188 mutex_init(&data->update_lock);
191 189
192 /* Register sysfs hooks */ 190 hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
193 ret = sysfs_create_group(&client->dev.kobj, &ltc4151_group); 191 data,
194 if (ret) 192 ltc4151_groups);
195 return ret; 193 return PTR_ERR_OR_ZERO(hwmon_dev);
196
197 data->hwmon_dev = hwmon_device_register(&client->dev);
198 if (IS_ERR(data->hwmon_dev)) {
199 ret = PTR_ERR(data->hwmon_dev);
200 goto out_hwmon_device_register;
201 }
202
203 return 0;
204
205out_hwmon_device_register:
206 sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
207 return ret;
208}
209
210static int ltc4151_remove(struct i2c_client *client)
211{
212 struct ltc4151_data *data = i2c_get_clientdata(client);
213
214 hwmon_device_unregister(data->hwmon_dev);
215 sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
216
217 return 0;
218} 194}
219 195
220static const struct i2c_device_id ltc4151_id[] = { 196static const struct i2c_device_id ltc4151_id[] = {
@@ -229,7 +205,6 @@ static struct i2c_driver ltc4151_driver = {
229 .name = "ltc4151", 205 .name = "ltc4151",
230 }, 206 },
231 .probe = ltc4151_probe, 207 .probe = ltc4151_probe,
232 .remove = ltc4151_remove,
233 .id_table = ltc4151_id, 208 .id_table = ltc4151_id,
234}; 209};
235 210
diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c
new file mode 100644
index 000000000000..decd7df995ab
--- /dev/null
+++ b/drivers/hwmon/shtc1.c
@@ -0,0 +1,251 @@
1/* Sensirion SHTC1 humidity and temperature sensor driver
2 *
3 * Copyright (C) 2014 Sensirion AG, Switzerland
4 * Author: Johannes Winkelmann <johannes.winkelmann@sensirion.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/i2c.h>
22#include <linux/hwmon.h>
23#include <linux/hwmon-sysfs.h>
24#include <linux/err.h>
25#include <linux/delay.h>
26#include <linux/platform_data/shtc1.h>
27
28/* commands (high precision mode) */
29static const unsigned char shtc1_cmd_measure_blocking_hpm[] = { 0x7C, 0xA2 };
30static const unsigned char shtc1_cmd_measure_nonblocking_hpm[] = { 0x78, 0x66 };
31
32/* commands (low precision mode) */
33static const unsigned char shtc1_cmd_measure_blocking_lpm[] = { 0x64, 0x58 };
34static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c };
35
36/* command for reading the ID register */
37static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 };
38
39/* constants for reading the ID register */
40#define SHTC1_ID 0x07
41#define SHTC1_ID_REG_MASK 0x1f
42
43/* delays for non-blocking i2c commands, both in us */
44#define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400
45#define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000
46
47#define SHTC1_CMD_LENGTH 2
48#define SHTC1_RESPONSE_LENGTH 6
49
50struct shtc1_data {
51 struct i2c_client *client;
52 struct mutex update_lock;
53 bool valid;
54 unsigned long last_updated; /* in jiffies */
55
56 const unsigned char *command;
57 unsigned int nonblocking_wait_time; /* in us */
58
59 struct shtc1_platform_data setup;
60
61 int temperature; /* 1000 * temperature in dgr C */
62 int humidity; /* 1000 * relative humidity in %RH */
63};
64
65static int shtc1_update_values(struct i2c_client *client,
66 struct shtc1_data *data,
67 char *buf, int bufsize)
68{
69 int ret = i2c_master_send(client, data->command, SHTC1_CMD_LENGTH);
70 if (ret != SHTC1_CMD_LENGTH) {
71 dev_err(&client->dev, "failed to send command: %d\n", ret);
72 return ret < 0 ? ret : -EIO;
73 }
74
75 /*
76 * In blocking mode (clock stretching mode) the I2C bus
77 * is blocked for other traffic, thus the call to i2c_master_recv()
78 * will wait until the data is ready. For non blocking mode, we
79 * have to wait ourselves.
80 */
81 if (!data->setup.blocking_io)
82 usleep_range(data->nonblocking_wait_time,
83 data->nonblocking_wait_time + 1000);
84
85 ret = i2c_master_recv(client, buf, bufsize);
86 if (ret != bufsize) {
87 dev_err(&client->dev, "failed to read values: %d\n", ret);
88 return ret < 0 ? ret : -EIO;
89 }
90
91 return 0;
92}
93
94/* sysfs attributes */
95static struct shtc1_data *shtc1_update_client(struct device *dev)
96{
97 struct shtc1_data *data = dev_get_drvdata(dev);
98 struct i2c_client *client = data->client;
99 unsigned char buf[SHTC1_RESPONSE_LENGTH];
100 int val;
101 int ret = 0;
102
103 mutex_lock(&data->update_lock);
104
105 if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) {
106 ret = shtc1_update_values(client, data, buf, sizeof(buf));
107 if (ret)
108 goto out;
109
110 /*
111 * From datasheet:
112 * T = -45 + 175 * ST / 2^16
113 * RH = 100 * SRH / 2^16
114 *
115 * Adapted for integer fixed point (3 digit) arithmetic.
116 */
117 val = be16_to_cpup((__be16 *)buf);
118 data->temperature = ((21875 * val) >> 13) - 45000;
119 val = be16_to_cpup((__be16 *)(buf + 3));
120 data->humidity = ((12500 * val) >> 13);
121
122 data->last_updated = jiffies;
123 data->valid = true;
124 }
125
126out:
127 mutex_unlock(&data->update_lock);
128
129 return ret == 0 ? data : ERR_PTR(ret);
130}
131
132static ssize_t temp1_input_show(struct device *dev,
133 struct device_attribute *attr,
134 char *buf)
135{
136 struct shtc1_data *data = shtc1_update_client(dev);
137 if (IS_ERR(data))
138 return PTR_ERR(data);
139
140 return sprintf(buf, "%d\n", data->temperature);
141}
142
143static ssize_t humidity1_input_show(struct device *dev,
144 struct device_attribute *attr, char *buf)
145{
146 struct shtc1_data *data = shtc1_update_client(dev);
147 if (IS_ERR(data))
148 return PTR_ERR(data);
149
150 return sprintf(buf, "%d\n", data->humidity);
151}
152
153static DEVICE_ATTR_RO(temp1_input);
154static DEVICE_ATTR_RO(humidity1_input);
155
156static struct attribute *shtc1_attrs[] = {
157 &dev_attr_temp1_input.attr,
158 &dev_attr_humidity1_input.attr,
159 NULL
160};
161
162ATTRIBUTE_GROUPS(shtc1);
163
164static void shtc1_select_command(struct shtc1_data *data)
165{
166 if (data->setup.high_precision) {
167 data->command = data->setup.blocking_io ?
168 shtc1_cmd_measure_blocking_hpm :
169 shtc1_cmd_measure_nonblocking_hpm;
170 data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_HPM;
171
172 } else {
173 data->command = data->setup.blocking_io ?
174 shtc1_cmd_measure_blocking_lpm :
175 shtc1_cmd_measure_nonblocking_lpm;
176 data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_LPM;
177 }
178}
179
180static int shtc1_probe(struct i2c_client *client,
181 const struct i2c_device_id *id)
182{
183 int ret;
184 char id_reg[2];
185 struct shtc1_data *data;
186 struct device *hwmon_dev;
187 struct i2c_adapter *adap = client->adapter;
188 struct device *dev = &client->dev;
189
190 if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) {
191 dev_err(dev, "plain i2c transactions not supported\n");
192 return -ENODEV;
193 }
194
195 ret = i2c_master_send(client, shtc1_cmd_read_id_reg, SHTC1_CMD_LENGTH);
196 if (ret != SHTC1_CMD_LENGTH) {
197 dev_err(dev, "could not send read_id_reg command: %d\n", ret);
198 return ret < 0 ? ret : -ENODEV;
199 }
200 ret = i2c_master_recv(client, id_reg, sizeof(id_reg));
201 if (ret != sizeof(id_reg)) {
202 dev_err(dev, "could not read ID register: %d\n", ret);
203 return -ENODEV;
204 }
205 if ((id_reg[1] & SHTC1_ID_REG_MASK) != SHTC1_ID) {
206 dev_err(dev, "ID register doesn't match\n");
207 return -ENODEV;
208 }
209
210 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
211 if (!data)
212 return -ENOMEM;
213
214 data->setup.blocking_io = false;
215 data->setup.high_precision = true;
216 data->client = client;
217
218 if (client->dev.platform_data)
219 data->setup = *(struct shtc1_platform_data *)dev->platform_data;
220 shtc1_select_command(data);
221 mutex_init(&data->update_lock);
222
223 hwmon_dev = devm_hwmon_device_register_with_groups(dev,
224 client->name,
225 data,
226 shtc1_groups);
227 if (IS_ERR(hwmon_dev))
228 dev_dbg(dev, "unable to register hwmon device\n");
229
230 return PTR_ERR_OR_ZERO(hwmon_dev);
231}
232
233/* device ID table */
234static const struct i2c_device_id shtc1_id[] = {
235 { "shtc1", 0 },
236 { "shtw1", 0 },
237 { }
238};
239MODULE_DEVICE_TABLE(i2c, shtc1_id);
240
241static struct i2c_driver shtc1_i2c_driver = {
242 .driver.name = "shtc1",
243 .probe = shtc1_probe,
244 .id_table = shtc1_id,
245};
246
247module_i2c_driver(shtc1_i2c_driver);
248
249MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>");
250MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver");
251MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
index 611f34c7333d..c53619086f33 100644
--- a/drivers/hwmon/vexpress.c
+++ b/drivers/hwmon/vexpress.c
@@ -27,17 +27,8 @@
27struct vexpress_hwmon_data { 27struct vexpress_hwmon_data {
28 struct device *hwmon_dev; 28 struct device *hwmon_dev;
29 struct regmap *reg; 29 struct regmap *reg;
30 const char *name;
31}; 30};
32 31
33static ssize_t vexpress_hwmon_name_show(struct device *dev,
34 struct device_attribute *dev_attr, char *buffer)
35{
36 struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
37
38 return sprintf(buffer, "%s\n", data->name);
39}
40
41static ssize_t vexpress_hwmon_label_show(struct device *dev, 32static ssize_t vexpress_hwmon_label_show(struct device *dev,
42 struct device_attribute *dev_attr, char *buffer) 33 struct device_attribute *dev_attr, char *buffer)
43{ 34{
@@ -95,16 +86,6 @@ static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
95 return attr->mode; 86 return attr->mode;
96} 87}
97 88
98static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL);
99
100#define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \
101struct attribute *vexpress_hwmon_attrs_##_name[] = { \
102 &dev_attr_name.attr, \
103 &dev_attr_##_label_attr.attr, \
104 &sensor_dev_attr_##_input_attr.dev_attr.attr, \
105 NULL \
106}
107
108struct vexpress_hwmon_type { 89struct vexpress_hwmon_type {
109 const char *name; 90 const char *name;
110 const struct attribute_group **attr_groups; 91 const struct attribute_group **attr_groups;
@@ -114,7 +95,11 @@ struct vexpress_hwmon_type {
114static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 95static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
115static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, 96static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
116 NULL, 1000); 97 NULL, 1000);
117static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input); 98static struct attribute *vexpress_hwmon_attrs_volt[] = {
99 &dev_attr_in1_label.attr,
100 &sensor_dev_attr_in1_input.dev_attr.attr,
101 NULL
102};
118static struct attribute_group vexpress_hwmon_group_volt = { 103static struct attribute_group vexpress_hwmon_group_volt = {
119 .is_visible = vexpress_hwmon_attr_is_visible, 104 .is_visible = vexpress_hwmon_attr_is_visible,
120 .attrs = vexpress_hwmon_attrs_volt, 105 .attrs = vexpress_hwmon_attrs_volt,
@@ -131,7 +116,11 @@ static struct vexpress_hwmon_type vexpress_hwmon_volt = {
131static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 116static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
132static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, 117static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
133 NULL, 1000); 118 NULL, 1000);
134static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input); 119static struct attribute *vexpress_hwmon_attrs_amp[] = {
120 &dev_attr_curr1_label.attr,
121 &sensor_dev_attr_curr1_input.dev_attr.attr,
122 NULL
123};
135static struct attribute_group vexpress_hwmon_group_amp = { 124static struct attribute_group vexpress_hwmon_group_amp = {
136 .is_visible = vexpress_hwmon_attr_is_visible, 125 .is_visible = vexpress_hwmon_attr_is_visible,
137 .attrs = vexpress_hwmon_attrs_amp, 126 .attrs = vexpress_hwmon_attrs_amp,
@@ -147,7 +136,11 @@ static struct vexpress_hwmon_type vexpress_hwmon_amp = {
147static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 136static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
148static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, 137static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
149 NULL, 1000); 138 NULL, 1000);
150static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input); 139static struct attribute *vexpress_hwmon_attrs_temp[] = {
140 &dev_attr_temp1_label.attr,
141 &sensor_dev_attr_temp1_input.dev_attr.attr,
142 NULL
143};
151static struct attribute_group vexpress_hwmon_group_temp = { 144static struct attribute_group vexpress_hwmon_group_temp = {
152 .is_visible = vexpress_hwmon_attr_is_visible, 145 .is_visible = vexpress_hwmon_attr_is_visible,
153 .attrs = vexpress_hwmon_attrs_temp, 146 .attrs = vexpress_hwmon_attrs_temp,
@@ -163,7 +156,11 @@ static struct vexpress_hwmon_type vexpress_hwmon_temp = {
163static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 156static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
164static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, 157static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
165 NULL, 1); 158 NULL, 1);
166static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input); 159static struct attribute *vexpress_hwmon_attrs_power[] = {
160 &dev_attr_power1_label.attr,
161 &sensor_dev_attr_power1_input.dev_attr.attr,
162 NULL
163};
167static struct attribute_group vexpress_hwmon_group_power = { 164static struct attribute_group vexpress_hwmon_group_power = {
168 .is_visible = vexpress_hwmon_attr_is_visible, 165 .is_visible = vexpress_hwmon_attr_is_visible,
169 .attrs = vexpress_hwmon_attrs_power, 166 .attrs = vexpress_hwmon_attrs_power,
@@ -179,7 +176,11 @@ static struct vexpress_hwmon_type vexpress_hwmon_power = {
179static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 176static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
180static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, 177static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
181 NULL, 1); 178 NULL, 1);
182static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input); 179static struct attribute *vexpress_hwmon_attrs_energy[] = {
180 &dev_attr_energy1_label.attr,
181 &sensor_dev_attr_energy1_input.dev_attr.attr,
182 NULL
183};
183static struct attribute_group vexpress_hwmon_group_energy = { 184static struct attribute_group vexpress_hwmon_group_energy = {
184 .is_visible = vexpress_hwmon_attr_is_visible, 185 .is_visible = vexpress_hwmon_attr_is_visible,
185 .attrs = vexpress_hwmon_attrs_energy, 186 .attrs = vexpress_hwmon_attrs_energy,
@@ -218,7 +219,6 @@ MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
218 219
219static int vexpress_hwmon_probe(struct platform_device *pdev) 220static int vexpress_hwmon_probe(struct platform_device *pdev)
220{ 221{
221 int err;
222 const struct of_device_id *match; 222 const struct of_device_id *match;
223 struct vexpress_hwmon_data *data; 223 struct vexpress_hwmon_data *data;
224 const struct vexpress_hwmon_type *type; 224 const struct vexpress_hwmon_type *type;
@@ -232,45 +232,19 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
232 if (!match) 232 if (!match)
233 return -ENODEV; 233 return -ENODEV;
234 type = match->data; 234 type = match->data;
235 data->name = type->name;
236 235
237 data->reg = devm_regmap_init_vexpress_config(&pdev->dev); 236 data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
238 if (IS_ERR(data->reg)) 237 if (IS_ERR(data->reg))
239 return PTR_ERR(data->reg); 238 return PTR_ERR(data->reg);
240 239
241 err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups); 240 data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
242 if (err) 241 type->name, data, type->attr_groups);
243 goto error;
244
245 data->hwmon_dev = hwmon_device_register(&pdev->dev);
246 if (IS_ERR(data->hwmon_dev)) {
247 err = PTR_ERR(data->hwmon_dev);
248 goto error;
249 }
250
251 return 0;
252
253error:
254 sysfs_remove_group(&pdev->dev.kobj, match->data);
255 return err;
256}
257
258static int vexpress_hwmon_remove(struct platform_device *pdev)
259{
260 struct vexpress_hwmon_data *data = platform_get_drvdata(pdev);
261 const struct of_device_id *match;
262
263 hwmon_device_unregister(data->hwmon_dev);
264
265 match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
266 sysfs_remove_group(&pdev->dev.kobj, match->data);
267 242
268 return 0; 243 return PTR_ERR_OR_ZERO(data->hwmon_dev);
269} 244}
270 245
271static struct platform_driver vexpress_hwmon_driver = { 246static struct platform_driver vexpress_hwmon_driver = {
272 .probe = vexpress_hwmon_probe, 247 .probe = vexpress_hwmon_probe,
273 .remove = vexpress_hwmon_remove,
274 .driver = { 248 .driver = {
275 .name = DRVNAME, 249 .name = DRVNAME,
276 .owner = THIS_MODULE, 250 .owner = THIS_MODULE,
diff --git a/include/linux/platform_data/shtc1.h b/include/linux/platform_data/shtc1.h
new file mode 100644
index 000000000000..7b8c353f7dc8
--- /dev/null
+++ b/include/linux/platform_data/shtc1.h
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2014 Sensirion AG, Switzerland
3 * Author: Johannes Winkelmann <johannes.winkelmann@sensirion.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#ifndef __SHTC1_H_
17#define __SHTC1_H_
18
19struct shtc1_platform_data {
20 bool blocking_io;
21 bool high_precision;
22};
23#endif /* __SHTC1_H_ */