Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull hwmon updates from Guenter Roeck:
- new driver for Sensirion SHTC1 humidity / temperature sensor
- convert ltc4151 and vexpress drivers to use devm functions
- drop generic chip detection from lm85 driver
- avoid forward declarations in atxp1 driver
- fix sign extensions in ina2xx driver

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
hwmon: vexpress: Use devm helper for hwmon device registration
hwmon: (atxp1) Avoid forward declaration
hwmon: add support for Sensirion SHTC1 sensor
hwmon: (ltc4151) Convert to devm_hwmon_device_register_with_groups
hwmon: (lm85) Drop generic detection
hwmon: (ina2xx) Cast to s16 on shunt and current regs

+401 -142
+43
Documentation/hwmon/shtc1
··· 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
+10
drivers/hwmon/Kconfig
··· 1124 1124 This driver can also be built as a module. If so, the module 1125 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 1137 config SENSORS_S3C 1128 1138 tristate "Samsung built-in ADC" 1129 1139 depends on S3C_ADC
+1
drivers/hwmon/Makefile
··· 126 126 obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o 127 127 obj-$(CONFIG_SENSORS_SHT15) += sht15.o 128 128 obj-$(CONFIG_SENSORS_SHT21) += sht21.o 129 + obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o 129 130 obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o 130 131 obj-$(CONFIG_SENSORS_SMM665) += smm665.o 131 132 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
+18 -24
drivers/hwmon/atxp1.c
··· 45 45 46 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 48 struct atxp1_data { 73 49 struct device *hwmon_dev; 74 50 struct mutex update_lock; ··· 360 384 sysfs_remove_group(&client->dev.kobj, &atxp1_group); 361 385 362 386 return 0; 387 + }; 388 + 389 + static const struct i2c_device_id atxp1_id[] = { 390 + { "atxp1", 0 }, 391 + { } 392 + }; 393 + MODULE_DEVICE_TABLE(i2c, atxp1_id); 394 + 395 + static struct i2c_driver atxp1_driver = { 396 + .class = I2C_CLASS_HWMON, 397 + .driver = { 398 + .name = "atxp1", 399 + }, 400 + .probe = atxp1_probe, 401 + .remove = atxp1_remove, 402 + .id_table = atxp1_id, 403 + .detect = atxp1_detect, 404 + .address_list = normal_i2c, 363 405 }; 364 406 365 407 module_i2c_driver(atxp1_driver);
+4 -3
drivers/hwmon/ina2xx.c
··· 148 148 149 149 switch (reg) { 150 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 153 data->config->shunt_div); 153 154 break; 154 155 case INA2XX_BUS_VOLTAGE: ··· 161 160 val = data->regs[reg] * data->config->power_lsb; 162 161 break; 163 162 case INA2XX_CURRENT: 164 - /* LSB=1mA (selected). Is in mA */ 165 - val = data->regs[reg]; 163 + /* signed register, LSB=1mA (selected), in mA */ 164 + val = (s16)data->regs[reg]; 166 165 break; 167 166 default: 168 167 /* programmer goofed */
+10 -23
drivers/hwmon/lm85.c
··· 5 5 * Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> 6 6 * Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de> 7 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 10 * Chip details at <http://www.national.com/ds/LM/LM85.pdf> 11 11 * ··· 39 39 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 40 40 41 41 enum chips { 42 - any_chip, lm85b, lm85c, 42 + lm85, 43 43 adm1027, adt7463, adt7468, 44 44 emc6d100, emc6d102, emc6d103, emc6d103s 45 45 }; ··· 75 75 #define LM85_COMPANY_NATIONAL 0x01 76 76 #define LM85_COMPANY_ANALOG_DEV 0x41 77 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 78 #define LM85_VERSTEP_LM85C 0x60 82 79 #define LM85_VERSTEP_LM85B 0x62 83 80 #define LM85_VERSTEP_LM96000_1 0x68 ··· 348 351 { "adm1027", adm1027 }, 349 352 { "adt7463", adt7463 }, 350 353 { "adt7468", adt7468 }, 351 - { "lm85", any_chip }, 352 - { "lm85b", lm85b }, 353 - { "lm85c", lm85c }, 354 + { "lm85", lm85 }, 355 + { "lm85b", lm85 }, 356 + { "lm85c", lm85 }, 354 357 { "emc6d100", emc6d100 }, 355 358 { "emc6d101", emc6d100 }, 356 359 { "emc6d102", emc6d102 }, ··· 1278 1281 { 1279 1282 struct i2c_adapter *adapter = client->adapter; 1280 1283 int address = client->addr; 1281 - const char *type_name; 1284 + const char *type_name = NULL; 1282 1285 int company, verstep; 1283 1286 1284 1287 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ··· 1294 1297 "Detecting device at 0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n", 1295 1298 address, company, verstep); 1296 1299 1297 - /* All supported chips have the version in common */ 1298 - if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && 1299 - (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { 1300 - dev_dbg(&adapter->dev, 1301 - "Autodetection failed: unsupported version\n"); 1302 - return -ENODEV; 1303 - } 1304 - type_name = "lm85"; 1305 - 1306 - /* Now, refine the detection */ 1307 1300 if (company == LM85_COMPANY_NATIONAL) { 1308 1301 switch (verstep) { 1309 1302 case LM85_VERSTEP_LM85C: ··· 1310 1323 "Found Winbond WPCD377I, ignoring\n"); 1311 1324 return -ENODEV; 1312 1325 } 1326 + type_name = "lm85"; 1313 1327 break; 1314 1328 } 1315 1329 } else if (company == LM85_COMPANY_ANALOG_DEV) { ··· 1345 1357 type_name = "emc6d103s"; 1346 1358 break; 1347 1359 } 1348 - } else { 1349 - dev_dbg(&adapter->dev, 1350 - "Autodetection failed: unknown vendor\n"); 1351 - return -ENODEV; 1352 1360 } 1361 + 1362 + if (!type_name) 1363 + return -ENODEV; 1353 1364 1354 1365 strlcpy(info->type, type_name, I2C_NAME_SIZE); 1355 1366
+13 -38
drivers/hwmon/ltc4151.c
··· 47 47 #define LTC4151_ADIN_L 0x05 48 48 49 49 struct ltc4151_data { 50 - struct device *hwmon_dev; 50 + struct i2c_client *client; 51 51 52 52 struct mutex update_lock; 53 53 bool valid; ··· 59 59 60 60 static struct ltc4151_data *ltc4151_update_device(struct device *dev) 61 61 { 62 - struct i2c_client *client = to_i2c_client(dev); 63 - struct ltc4151_data *data = i2c_get_clientdata(client); 62 + struct ltc4151_data *data = dev_get_drvdata(dev); 63 + struct i2c_client *client = data->client; 64 64 struct ltc4151_data *ret = data; 65 65 66 66 mutex_lock(&data->update_lock); ··· 159 159 * Finally, construct an array of pointers to members of the above objects, 160 160 * as required for sysfs_create_group() 161 161 */ 162 - static struct attribute *ltc4151_attributes[] = { 162 + static struct attribute *ltc4151_attrs[] = { 163 163 &sensor_dev_attr_in1_input.dev_attr.attr, 164 164 &sensor_dev_attr_in2_input.dev_attr.attr, 165 165 ··· 167 167 168 168 NULL, 169 169 }; 170 - 171 - static const struct attribute_group ltc4151_group = { 172 - .attrs = ltc4151_attributes, 173 - }; 170 + ATTRIBUTE_GROUPS(ltc4151); 174 171 175 172 static int ltc4151_probe(struct i2c_client *client, 176 173 const struct i2c_device_id *id) 177 174 { 178 175 struct i2c_adapter *adapter = client->adapter; 176 + struct device *dev = &client->dev; 179 177 struct ltc4151_data *data; 180 - int ret; 178 + struct device *hwmon_dev; 181 179 182 180 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 183 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 184 if (!data) 187 185 return -ENOMEM; 188 186 189 - i2c_set_clientdata(client, data); 187 + data->client = client; 190 188 mutex_init(&data->update_lock); 191 189 192 - /* Register sysfs hooks */ 193 - ret = sysfs_create_group(&client->dev.kobj, &ltc4151_group); 194 - if (ret) 195 - return ret; 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, &ltc4151_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, &ltc4151_group); 216 - 217 - return 0; 190 + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, 191 + data, 192 + ltc4151_groups); 193 + return PTR_ERR_OR_ZERO(hwmon_dev); 218 194 } 219 195 220 196 static const struct i2c_device_id ltc4151_id[] = { ··· 205 229 .name = "ltc4151", 206 230 }, 207 231 .probe = ltc4151_probe, 208 - .remove = ltc4151_remove, 209 232 .id_table = ltc4151_id, 210 233 }; 211 234
+251
drivers/hwmon/shtc1.c
··· 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");
+28 -54
drivers/hwmon/vexpress.c
··· 27 27 struct vexpress_hwmon_data { 28 28 struct device *hwmon_dev; 29 29 struct regmap *reg; 30 - const char *name; 31 30 }; 32 - 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 31 41 32 static ssize_t vexpress_hwmon_label_show(struct device *dev, 42 33 struct device_attribute *dev_attr, char *buffer) ··· 86 95 return attr->mode; 87 96 } 88 97 89 - static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL); 90 - 91 - #define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \ 92 - struct attribute *vexpress_hwmon_attrs_##_name[] = { \ 93 - &dev_attr_name.attr, \ 94 - &dev_attr_##_label_attr.attr, \ 95 - &sensor_dev_attr_##_input_attr.dev_attr.attr, \ 96 - NULL \ 97 - } 98 - 99 98 struct vexpress_hwmon_type { 100 99 const char *name; 101 100 const struct attribute_group **attr_groups; ··· 95 114 static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 96 115 static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show, 97 116 NULL, 1000); 98 - static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input); 117 + static struct attribute *vexpress_hwmon_attrs_volt[] = { 118 + &dev_attr_in1_label.attr, 119 + &sensor_dev_attr_in1_input.dev_attr.attr, 120 + NULL 121 + }; 99 122 static struct attribute_group vexpress_hwmon_group_volt = { 100 123 .is_visible = vexpress_hwmon_attr_is_visible, 101 124 .attrs = vexpress_hwmon_attrs_volt, ··· 116 131 static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 117 132 static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show, 118 133 NULL, 1000); 119 - static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input); 134 + static struct attribute *vexpress_hwmon_attrs_amp[] = { 135 + &dev_attr_curr1_label.attr, 136 + &sensor_dev_attr_curr1_input.dev_attr.attr, 137 + NULL 138 + }; 120 139 static struct attribute_group vexpress_hwmon_group_amp = { 121 140 .is_visible = vexpress_hwmon_attr_is_visible, 122 141 .attrs = vexpress_hwmon_attrs_amp, ··· 136 147 static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 137 148 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show, 138 149 NULL, 1000); 139 - static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input); 150 + static struct attribute *vexpress_hwmon_attrs_temp[] = { 151 + &dev_attr_temp1_label.attr, 152 + &sensor_dev_attr_temp1_input.dev_attr.attr, 153 + NULL 154 + }; 140 155 static struct attribute_group vexpress_hwmon_group_temp = { 141 156 .is_visible = vexpress_hwmon_attr_is_visible, 142 157 .attrs = vexpress_hwmon_attrs_temp, ··· 156 163 static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 157 164 static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show, 158 165 NULL, 1); 159 - static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input); 166 + static struct attribute *vexpress_hwmon_attrs_power[] = { 167 + &dev_attr_power1_label.attr, 168 + &sensor_dev_attr_power1_input.dev_attr.attr, 169 + NULL 170 + }; 160 171 static struct attribute_group vexpress_hwmon_group_power = { 161 172 .is_visible = vexpress_hwmon_attr_is_visible, 162 173 .attrs = vexpress_hwmon_attrs_power, ··· 176 179 static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL); 177 180 static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show, 178 181 NULL, 1); 179 - static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input); 182 + static struct attribute *vexpress_hwmon_attrs_energy[] = { 183 + &dev_attr_energy1_label.attr, 184 + &sensor_dev_attr_energy1_input.dev_attr.attr, 185 + NULL 186 + }; 180 187 static struct attribute_group vexpress_hwmon_group_energy = { 181 188 .is_visible = vexpress_hwmon_attr_is_visible, 182 189 .attrs = vexpress_hwmon_attrs_energy, ··· 219 218 220 219 static int vexpress_hwmon_probe(struct platform_device *pdev) 221 220 { 222 - int err; 223 221 const struct of_device_id *match; 224 222 struct vexpress_hwmon_data *data; 225 223 const struct vexpress_hwmon_type *type; ··· 232 232 if (!match) 233 233 return -ENODEV; 234 234 type = match->data; 235 - data->name = type->name; 236 235 237 236 data->reg = devm_regmap_init_vexpress_config(&pdev->dev); 238 237 if (IS_ERR(data->reg)) 239 238 return PTR_ERR(data->reg); 240 239 241 - err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups); 242 - if (err) 243 - goto error; 240 + data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, 241 + type->name, data, type->attr_groups); 244 242 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 - 268 - return 0; 243 + return PTR_ERR_OR_ZERO(data->hwmon_dev); 269 244 } 270 245 271 246 static struct platform_driver vexpress_hwmon_driver = { 272 247 .probe = vexpress_hwmon_probe, 273 - .remove = vexpress_hwmon_remove, 274 248 .driver = { 275 249 .name = DRVNAME, 276 250 .owner = THIS_MODULE,
+23
include/linux/platform_data/shtc1.h
··· 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_ */