| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 9 | 10 | * Very rare chip please let me know if you use it |
|---|
| 10 | 11 | * |
|---|
| 11 | 12 | * http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf |
|---|
| 12 | | - * |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 15 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 16 | | - * the Free Software Foundation version 2 of the License |
|---|
| 17 | | - * |
|---|
| 18 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 19 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 21 | | - * GNU General Public License for more details. |
|---|
| 22 | | - * |
|---|
| 23 | | - * You should have received a copy of the GNU General Public License |
|---|
| 24 | | - * along with this program; if not, write to the Free Software |
|---|
| 25 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 26 | 13 | */ |
|---|
| 27 | 14 | |
|---|
| 28 | 15 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 111 | 98 | |
|---|
| 112 | 99 | struct adm1029_data { |
|---|
| 113 | 100 | struct i2c_client *client; |
|---|
| 114 | | - struct mutex update_lock; |
|---|
| 101 | + struct mutex update_lock; /* protect register access */ |
|---|
| 115 | 102 | char valid; /* zero until following fields are valid */ |
|---|
| 116 | 103 | unsigned long last_updated; /* in jiffies */ |
|---|
| 117 | 104 | |
|---|
| .. | .. |
|---|
| 134 | 121 | * Use the "cache" Luke, don't recheck values |
|---|
| 135 | 122 | * if there are already checked not a long time later |
|---|
| 136 | 123 | */ |
|---|
| 137 | | - if (time_after(jiffies, data->last_updated + HZ * 2) |
|---|
| 138 | | - || !data->valid) { |
|---|
| 124 | + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { |
|---|
| 139 | 125 | int nr; |
|---|
| 140 | 126 | |
|---|
| 141 | 127 | dev_dbg(&client->dev, "Updating adm1029 data\n"); |
|---|
| .. | .. |
|---|
| 170 | 156 | */ |
|---|
| 171 | 157 | |
|---|
| 172 | 158 | static ssize_t |
|---|
| 173 | | -show_temp(struct device *dev, struct device_attribute *devattr, char *buf) |
|---|
| 159 | +temp_show(struct device *dev, struct device_attribute *devattr, char *buf) |
|---|
| 174 | 160 | { |
|---|
| 175 | 161 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
|---|
| 176 | 162 | struct adm1029_data *data = adm1029_update_device(dev); |
|---|
| 163 | + |
|---|
| 177 | 164 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); |
|---|
| 178 | 165 | } |
|---|
| 179 | 166 | |
|---|
| 180 | 167 | static ssize_t |
|---|
| 181 | | -show_fan(struct device *dev, struct device_attribute *devattr, char *buf) |
|---|
| 168 | +fan_show(struct device *dev, struct device_attribute *devattr, char *buf) |
|---|
| 182 | 169 | { |
|---|
| 183 | 170 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
|---|
| 184 | 171 | struct adm1029_data *data = adm1029_update_device(dev); |
|---|
| 185 | 172 | u16 val; |
|---|
| 186 | | - if (data->fan[attr->index] == 0 |
|---|
| 187 | | - || (data->fan_div[attr->index] & 0xC0) == 0 |
|---|
| 188 | | - || data->fan[attr->index] == 255) { |
|---|
| 173 | + |
|---|
| 174 | + if (data->fan[attr->index] == 0 || |
|---|
| 175 | + (data->fan_div[attr->index] & 0xC0) == 0 || |
|---|
| 176 | + data->fan[attr->index] == 255) { |
|---|
| 189 | 177 | return sprintf(buf, "0\n"); |
|---|
| 190 | 178 | } |
|---|
| 191 | 179 | |
|---|
| .. | .. |
|---|
| 195 | 183 | } |
|---|
| 196 | 184 | |
|---|
| 197 | 185 | static ssize_t |
|---|
| 198 | | -show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) |
|---|
| 186 | +fan_div_show(struct device *dev, struct device_attribute *devattr, char *buf) |
|---|
| 199 | 187 | { |
|---|
| 200 | 188 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
|---|
| 201 | 189 | struct adm1029_data *data = adm1029_update_device(dev); |
|---|
| 190 | + |
|---|
| 202 | 191 | if ((data->fan_div[attr->index] & 0xC0) == 0) |
|---|
| 203 | 192 | return sprintf(buf, "0\n"); |
|---|
| 204 | 193 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); |
|---|
| 205 | 194 | } |
|---|
| 206 | 195 | |
|---|
| 207 | | -static ssize_t set_fan_div(struct device *dev, |
|---|
| 208 | | - struct device_attribute *devattr, const char *buf, size_t count) |
|---|
| 196 | +static ssize_t fan_div_store(struct device *dev, |
|---|
| 197 | + struct device_attribute *devattr, |
|---|
| 198 | + const char *buf, size_t count) |
|---|
| 209 | 199 | { |
|---|
| 210 | 200 | struct adm1029_data *data = dev_get_drvdata(dev); |
|---|
| 211 | 201 | struct i2c_client *client = data->client; |
|---|
| .. | .. |
|---|
| 213 | 203 | u8 reg; |
|---|
| 214 | 204 | long val; |
|---|
| 215 | 205 | int ret = kstrtol(buf, 10, &val); |
|---|
| 206 | + |
|---|
| 216 | 207 | if (ret < 0) |
|---|
| 217 | 208 | return ret; |
|---|
| 218 | 209 | |
|---|
| .. | .. |
|---|
| 253 | 244 | return count; |
|---|
| 254 | 245 | } |
|---|
| 255 | 246 | |
|---|
| 256 | | -/* |
|---|
| 257 | | - * Access rights on sysfs. S_IRUGO: Is Readable by User, Group and Others |
|---|
| 258 | | - * S_IWUSR: Is Writable by User. |
|---|
| 259 | | - */ |
|---|
| 260 | | -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); |
|---|
| 261 | | -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); |
|---|
| 262 | | -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); |
|---|
| 247 | +/* Access rights on sysfs. */ |
|---|
| 248 | +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); |
|---|
| 249 | +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); |
|---|
| 250 | +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); |
|---|
| 263 | 251 | |
|---|
| 264 | | -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3); |
|---|
| 265 | | -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4); |
|---|
| 266 | | -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5); |
|---|
| 252 | +static SENSOR_DEVICE_ATTR_RO(temp1_max, temp, 3); |
|---|
| 253 | +static SENSOR_DEVICE_ATTR_RO(temp2_max, temp, 4); |
|---|
| 254 | +static SENSOR_DEVICE_ATTR_RO(temp3_max, temp, 5); |
|---|
| 267 | 255 | |
|---|
| 268 | | -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6); |
|---|
| 269 | | -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7); |
|---|
| 270 | | -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8); |
|---|
| 256 | +static SENSOR_DEVICE_ATTR_RO(temp1_min, temp, 6); |
|---|
| 257 | +static SENSOR_DEVICE_ATTR_RO(temp2_min, temp, 7); |
|---|
| 258 | +static SENSOR_DEVICE_ATTR_RO(temp3_min, temp, 8); |
|---|
| 271 | 259 | |
|---|
| 272 | | -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); |
|---|
| 273 | | -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); |
|---|
| 260 | +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); |
|---|
| 261 | +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); |
|---|
| 274 | 262 | |
|---|
| 275 | | -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2); |
|---|
| 276 | | -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3); |
|---|
| 263 | +static SENSOR_DEVICE_ATTR_RO(fan1_min, fan, 2); |
|---|
| 264 | +static SENSOR_DEVICE_ATTR_RO(fan2_min, fan, 3); |
|---|
| 277 | 265 | |
|---|
| 278 | | -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
|---|
| 279 | | - show_fan_div, set_fan_div, 0); |
|---|
| 280 | | -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, |
|---|
| 281 | | - show_fan_div, set_fan_div, 1); |
|---|
| 266 | +static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); |
|---|
| 267 | +static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); |
|---|
| 282 | 268 | |
|---|
| 283 | 269 | static struct attribute *adm1029_attrs[] = { |
|---|
| 284 | 270 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
|---|
| .. | .. |
|---|
| 327 | 313 | temp_devices_installed = i2c_smbus_read_byte_data(client, |
|---|
| 328 | 314 | ADM1029_REG_TEMP_DEVICES_INSTALLED); |
|---|
| 329 | 315 | nb_fan_support = i2c_smbus_read_byte_data(client, |
|---|
| 330 | | - ADM1029_REG_NB_FAN_SUPPORT); |
|---|
| 316 | + ADM1029_REG_NB_FAN_SUPPORT); |
|---|
| 331 | 317 | /* 0x41 is Analog Devices */ |
|---|
| 332 | | - if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01 |
|---|
| 333 | | - || nb_fan_support != 0x03) |
|---|
| 318 | + if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01 || |
|---|
| 319 | + nb_fan_support != 0x03) |
|---|
| 334 | 320 | return -ENODEV; |
|---|
| 335 | 321 | |
|---|
| 336 | 322 | if ((chip_id & 0xF0) != 0x00) { |
|---|
| .. | .. |
|---|
| 366 | 352 | return 1; |
|---|
| 367 | 353 | } |
|---|
| 368 | 354 | |
|---|
| 369 | | -static int adm1029_probe(struct i2c_client *client, |
|---|
| 370 | | - const struct i2c_device_id *id) |
|---|
| 355 | +static int adm1029_probe(struct i2c_client *client) |
|---|
| 371 | 356 | { |
|---|
| 372 | 357 | struct device *dev = &client->dev; |
|---|
| 373 | 358 | struct adm1029_data *data; |
|---|
| .. | .. |
|---|
| 404 | 389 | .driver = { |
|---|
| 405 | 390 | .name = "adm1029", |
|---|
| 406 | 391 | }, |
|---|
| 407 | | - .probe = adm1029_probe, |
|---|
| 392 | + .probe_new = adm1029_probe, |
|---|
| 408 | 393 | .id_table = adm1029_id, |
|---|
| 409 | 394 | .detect = adm1029_detect, |
|---|
| 410 | 395 | .address_list = normal_i2c, |
|---|