diff options
-rw-r--r-- | Documentation/hwmon/shtc1 | 43 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/atxp1.c | 42 | ||||
-rw-r--r-- | drivers/hwmon/ina2xx.c | 7 | ||||
-rw-r--r-- | drivers/hwmon/lm85.c | 33 | ||||
-rw-r--r-- | drivers/hwmon/ltc4151.c | 51 | ||||
-rw-r--r-- | drivers/hwmon/shtc1.c | 251 | ||||
-rw-r--r-- | drivers/hwmon/vexpress.c | 82 | ||||
-rw-r--r-- | include/linux/platform_data/shtc1.h | 23 |
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 @@ | |||
1 | Kernel driver shtc1 | ||
2 | =================== | ||
3 | |||
4 | Supported 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 | |||
15 | Author: | ||
16 | Johannes Winkelmann <johannes.winkelmann@sensirion.com> | ||
17 | |||
18 | Description | ||
19 | ----------- | ||
20 | |||
21 | This driver implements support for the Sensirion SHTC1 chip, a humidity and | ||
22 | temperature sensor. Temperature is measured in degrees celsius, relative | ||
23 | humidity is expressed as a percentage. Driver can be used as well for SHTW1 | ||
24 | chip, which has the same electrical interface. | ||
25 | |||
26 | The device communicates with the I2C protocol. All sensors are set to I2C | ||
27 | address 0x70. See Documentation/i2c/instantiating-devices for methods to | ||
28 | instantiate the device. | ||
29 | |||
30 | There are two options configurable by means of shtc1_platform_data: | ||
31 | 1. 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. | ||
36 | 2. high or low accuracy. High accuracy is used by default and using it is | ||
37 | strongly recommended. | ||
38 | |||
39 | sysfs-Interface | ||
40 | --------------- | ||
41 | |||
42 | temp1_input - temperature input | ||
43 | humidity1_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 | ||
1127 | config 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 | |||
1127 | config SENSORS_S3C | 1137 | config 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 | |||
126 | obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o | 126 | obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o |
127 | obj-$(CONFIG_SENSORS_SHT15) += sht15.o | 127 | obj-$(CONFIG_SENSORS_SHT15) += sht15.o |
128 | obj-$(CONFIG_SENSORS_SHT21) += sht21.o | 128 | obj-$(CONFIG_SENSORS_SHT21) += sht21.o |
129 | obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o | ||
129 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o | 130 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o |
130 | obj-$(CONFIG_SENSORS_SMM665) += smm665.o | 131 | obj-$(CONFIG_SENSORS_SMM665) += smm665.o |
131 | obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o | 132 | obj-$(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 | ||
46 | static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; | 46 | static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; |
47 | 47 | ||
48 | static int atxp1_probe(struct i2c_client *client, | ||
49 | const struct i2c_device_id *id); | ||
50 | static int atxp1_remove(struct i2c_client *client); | ||
51 | static struct atxp1_data *atxp1_update_device(struct device *dev); | ||
52 | static int atxp1_detect(struct i2c_client *client, struct i2c_board_info *info); | ||
53 | |||
54 | static const struct i2c_device_id atxp1_id[] = { | ||
55 | { "atxp1", 0 }, | ||
56 | { } | ||
57 | }; | ||
58 | MODULE_DEVICE_TABLE(i2c, atxp1_id); | ||
59 | |||
60 | static 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 | |||
72 | struct atxp1_data { | 48 | struct 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 | ||
365 | static const struct i2c_device_id atxp1_id[] = { | ||
366 | { "atxp1", 0 }, | ||
367 | { } | ||
368 | }; | ||
369 | MODULE_DEVICE_TABLE(i2c, atxp1_id); | ||
370 | |||
371 | static 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 | |||
389 | module_i2c_driver(atxp1_driver); | 383 | module_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 @@ | |||
39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 39 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
40 | 40 | ||
41 | enum chips { | 41 | enum 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 | ||
49 | struct ltc4151_data { | 49 | struct 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 | ||
60 | static struct ltc4151_data *ltc4151_update_device(struct device *dev) | 60 | static 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 | */ |
162 | static struct attribute *ltc4151_attributes[] = { | 162 | static 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 | 170 | ATTRIBUTE_GROUPS(ltc4151); | |
171 | static const struct attribute_group ltc4151_group = { | ||
172 | .attrs = ltc4151_attributes, | ||
173 | }; | ||
174 | 171 | ||
175 | static int ltc4151_probe(struct i2c_client *client, | 172 | static 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, <c4151_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 | |||
205 | out_hwmon_device_register: | ||
206 | sysfs_remove_group(&client->dev.kobj, <c4151_group); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static 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, <c4151_group); | ||
216 | |||
217 | return 0; | ||
218 | } | 194 | } |
219 | 195 | ||
220 | static const struct i2c_device_id ltc4151_id[] = { | 196 | static 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) */ | ||
29 | static const unsigned char shtc1_cmd_measure_blocking_hpm[] = { 0x7C, 0xA2 }; | ||
30 | static const unsigned char shtc1_cmd_measure_nonblocking_hpm[] = { 0x78, 0x66 }; | ||
31 | |||
32 | /* commands (low precision mode) */ | ||
33 | static const unsigned char shtc1_cmd_measure_blocking_lpm[] = { 0x64, 0x58 }; | ||
34 | static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c }; | ||
35 | |||
36 | /* command for reading the ID register */ | ||
37 | static 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 | |||
50 | struct 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 | |||
65 | static 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 */ | ||
95 | static 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 | |||
126 | out: | ||
127 | mutex_unlock(&data->update_lock); | ||
128 | |||
129 | return ret == 0 ? data : ERR_PTR(ret); | ||
130 | } | ||
131 | |||
132 | static 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 | |||
143 | static 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 | |||
153 | static DEVICE_ATTR_RO(temp1_input); | ||
154 | static DEVICE_ATTR_RO(humidity1_input); | ||
155 | |||
156 | static struct attribute *shtc1_attrs[] = { | ||
157 | &dev_attr_temp1_input.attr, | ||
158 | &dev_attr_humidity1_input.attr, | ||
159 | NULL | ||
160 | }; | ||
161 | |||
162 | ATTRIBUTE_GROUPS(shtc1); | ||
163 | |||
164 | static 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 | |||
180 | static 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 */ | ||
234 | static const struct i2c_device_id shtc1_id[] = { | ||
235 | { "shtc1", 0 }, | ||
236 | { "shtw1", 0 }, | ||
237 | { } | ||
238 | }; | ||
239 | MODULE_DEVICE_TABLE(i2c, shtc1_id); | ||
240 | |||
241 | static struct i2c_driver shtc1_i2c_driver = { | ||
242 | .driver.name = "shtc1", | ||
243 | .probe = shtc1_probe, | ||
244 | .id_table = shtc1_id, | ||
245 | }; | ||
246 | |||
247 | module_i2c_driver(shtc1_i2c_driver); | ||
248 | |||
249 | MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>"); | ||
250 | MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver"); | ||
251 | MODULE_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 @@ | |||
27 | struct vexpress_hwmon_data { | 27 | struct 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 | ||
33 | static 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 | |||
41 | static ssize_t vexpress_hwmon_label_show(struct device *dev, | 32 | static 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 | ||
98 | static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL); | ||
99 | |||
100 | #define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \ | ||
101 | struct 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 | |||
108 | struct vexpress_hwmon_type { | 89 | struct 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 { | |||
114 | static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | 95 | static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); |
115 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, | 96 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, |
116 | NULL, 1000); | 97 | NULL, 1000); |
117 | static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input); | 98 | static struct attribute *vexpress_hwmon_attrs_volt[] = { |
99 | &dev_attr_in1_label.attr, | ||
100 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
101 | NULL | ||
102 | }; | ||
118 | static struct attribute_group vexpress_hwmon_group_volt = { | 103 | static 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 = { | |||
131 | static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | 116 | static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); |
132 | static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, | 117 | static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, |
133 | NULL, 1000); | 118 | NULL, 1000); |
134 | static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input); | 119 | static struct attribute *vexpress_hwmon_attrs_amp[] = { |
120 | &dev_attr_curr1_label.attr, | ||
121 | &sensor_dev_attr_curr1_input.dev_attr.attr, | ||
122 | NULL | ||
123 | }; | ||
135 | static struct attribute_group vexpress_hwmon_group_amp = { | 124 | static 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 = { | |||
147 | static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | 136 | static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); |
148 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, | 137 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, |
149 | NULL, 1000); | 138 | NULL, 1000); |
150 | static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input); | 139 | static struct attribute *vexpress_hwmon_attrs_temp[] = { |
140 | &dev_attr_temp1_label.attr, | ||
141 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
142 | NULL | ||
143 | }; | ||
151 | static struct attribute_group vexpress_hwmon_group_temp = { | 144 | static 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 = { | |||
163 | static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | 156 | static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); |
164 | static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, | 157 | static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, |
165 | NULL, 1); | 158 | NULL, 1); |
166 | static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input); | 159 | static struct attribute *vexpress_hwmon_attrs_power[] = { |
160 | &dev_attr_power1_label.attr, | ||
161 | &sensor_dev_attr_power1_input.dev_attr.attr, | ||
162 | NULL | ||
163 | }; | ||
167 | static struct attribute_group vexpress_hwmon_group_power = { | 164 | static 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 = { | |||
179 | static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); | 176 | static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); |
180 | static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, | 177 | static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, |
181 | NULL, 1); | 178 | NULL, 1); |
182 | static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input); | 179 | static struct attribute *vexpress_hwmon_attrs_energy[] = { |
180 | &dev_attr_energy1_label.attr, | ||
181 | &sensor_dev_attr_energy1_input.dev_attr.attr, | ||
182 | NULL | ||
183 | }; | ||
183 | static struct attribute_group vexpress_hwmon_group_energy = { | 184 | static 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 | ||
219 | static int vexpress_hwmon_probe(struct platform_device *pdev) | 220 | static 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 | |||
253 | error: | ||
254 | sysfs_remove_group(&pdev->dev.kobj, match->data); | ||
255 | return err; | ||
256 | } | ||
257 | |||
258 | static 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 | ||
271 | static struct platform_driver vexpress_hwmon_driver = { | 246 | static 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 | |||
19 | struct shtc1_platform_data { | ||
20 | bool blocking_io; | ||
21 | bool high_precision; | ||
22 | }; | ||
23 | #endif /* __SHTC1_H_ */ | ||