| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * lm78.c - Part of lm_sensors, Linux kernel modules for hardware |
|---|
| 3 | 4 | * monitoring |
|---|
| 4 | 5 | * Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> |
|---|
| 5 | 6 | * Copyright (c) 2007, 2011 Jean Delvare <jdelvare@suse.de> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | | - * |
|---|
| 17 | | - * You should have received a copy of the GNU General Public License |
|---|
| 18 | | - * along with this program; if not, write to the Free Software |
|---|
| 19 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 20 | 7 | */ |
|---|
| 21 | 8 | |
|---|
| 22 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 72 | 59 | #define LM78_REG_CONFIG 0x40 |
|---|
| 73 | 60 | #define LM78_REG_CHIPID 0x49 |
|---|
| 74 | 61 | #define LM78_REG_I2C_ADDR 0x48 |
|---|
| 75 | | - |
|---|
| 76 | 62 | |
|---|
| 77 | 63 | /* |
|---|
| 78 | 64 | * Conversions. Rounding and limit checking is only done on the TO_REG |
|---|
| .. | .. |
|---|
| 147 | 133 | u16 alarms; /* Register encoding, combined */ |
|---|
| 148 | 134 | }; |
|---|
| 149 | 135 | |
|---|
| 150 | | - |
|---|
| 151 | 136 | static int lm78_read_value(struct lm78_data *data, u8 reg); |
|---|
| 152 | 137 | static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value); |
|---|
| 153 | 138 | static struct lm78_data *lm78_update_device(struct device *dev); |
|---|
| 154 | 139 | static void lm78_init_device(struct lm78_data *data); |
|---|
| 155 | 140 | |
|---|
| 156 | | - |
|---|
| 157 | 141 | /* 7 Voltages */ |
|---|
| 158 | | -static ssize_t show_in(struct device *dev, struct device_attribute *da, |
|---|
| 142 | +static ssize_t in_show(struct device *dev, struct device_attribute *da, |
|---|
| 159 | 143 | char *buf) |
|---|
| 160 | 144 | { |
|---|
| 161 | 145 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| .. | .. |
|---|
| 163 | 147 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index])); |
|---|
| 164 | 148 | } |
|---|
| 165 | 149 | |
|---|
| 166 | | -static ssize_t show_in_min(struct device *dev, struct device_attribute *da, |
|---|
| 150 | +static ssize_t in_min_show(struct device *dev, struct device_attribute *da, |
|---|
| 167 | 151 | char *buf) |
|---|
| 168 | 152 | { |
|---|
| 169 | 153 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| .. | .. |
|---|
| 171 | 155 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index])); |
|---|
| 172 | 156 | } |
|---|
| 173 | 157 | |
|---|
| 174 | | -static ssize_t show_in_max(struct device *dev, struct device_attribute *da, |
|---|
| 158 | +static ssize_t in_max_show(struct device *dev, struct device_attribute *da, |
|---|
| 175 | 159 | char *buf) |
|---|
| 176 | 160 | { |
|---|
| 177 | 161 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| .. | .. |
|---|
| 179 | 163 | return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index])); |
|---|
| 180 | 164 | } |
|---|
| 181 | 165 | |
|---|
| 182 | | -static ssize_t set_in_min(struct device *dev, struct device_attribute *da, |
|---|
| 183 | | - const char *buf, size_t count) |
|---|
| 166 | +static ssize_t in_min_store(struct device *dev, struct device_attribute *da, |
|---|
| 167 | + const char *buf, size_t count) |
|---|
| 184 | 168 | { |
|---|
| 185 | 169 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| 186 | 170 | struct lm78_data *data = dev_get_drvdata(dev); |
|---|
| .. | .. |
|---|
| 199 | 183 | return count; |
|---|
| 200 | 184 | } |
|---|
| 201 | 185 | |
|---|
| 202 | | -static ssize_t set_in_max(struct device *dev, struct device_attribute *da, |
|---|
| 203 | | - const char *buf, size_t count) |
|---|
| 186 | +static ssize_t in_max_store(struct device *dev, struct device_attribute *da, |
|---|
| 187 | + const char *buf, size_t count) |
|---|
| 204 | 188 | { |
|---|
| 205 | 189 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| 206 | 190 | struct lm78_data *data = dev_get_drvdata(dev); |
|---|
| .. | .. |
|---|
| 219 | 203 | return count; |
|---|
| 220 | 204 | } |
|---|
| 221 | 205 | |
|---|
| 222 | | -#define show_in_offset(offset) \ |
|---|
| 223 | | -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ |
|---|
| 224 | | - show_in, NULL, offset); \ |
|---|
| 225 | | -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ |
|---|
| 226 | | - show_in_min, set_in_min, offset); \ |
|---|
| 227 | | -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ |
|---|
| 228 | | - show_in_max, set_in_max, offset); |
|---|
| 229 | | - |
|---|
| 230 | | -show_in_offset(0); |
|---|
| 231 | | -show_in_offset(1); |
|---|
| 232 | | -show_in_offset(2); |
|---|
| 233 | | -show_in_offset(3); |
|---|
| 234 | | -show_in_offset(4); |
|---|
| 235 | | -show_in_offset(5); |
|---|
| 236 | | -show_in_offset(6); |
|---|
| 206 | +static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0); |
|---|
| 207 | +static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0); |
|---|
| 208 | +static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0); |
|---|
| 209 | +static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1); |
|---|
| 210 | +static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1); |
|---|
| 211 | +static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1); |
|---|
| 212 | +static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2); |
|---|
| 213 | +static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2); |
|---|
| 214 | +static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2); |
|---|
| 215 | +static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3); |
|---|
| 216 | +static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3); |
|---|
| 217 | +static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3); |
|---|
| 218 | +static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4); |
|---|
| 219 | +static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4); |
|---|
| 220 | +static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4); |
|---|
| 221 | +static SENSOR_DEVICE_ATTR_RO(in5_input, in, 5); |
|---|
| 222 | +static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5); |
|---|
| 223 | +static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5); |
|---|
| 224 | +static SENSOR_DEVICE_ATTR_RO(in6_input, in, 6); |
|---|
| 225 | +static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6); |
|---|
| 226 | +static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6); |
|---|
| 237 | 227 | |
|---|
| 238 | 228 | /* Temperature */ |
|---|
| 239 | 229 | static ssize_t temp1_input_show(struct device *dev, |
|---|
| .. | .. |
|---|
| 300 | 290 | static DEVICE_ATTR_RW(temp1_max_hyst); |
|---|
| 301 | 291 | |
|---|
| 302 | 292 | /* 3 Fans */ |
|---|
| 303 | | -static ssize_t show_fan(struct device *dev, struct device_attribute *da, |
|---|
| 293 | +static ssize_t fan_show(struct device *dev, struct device_attribute *da, |
|---|
| 304 | 294 | char *buf) |
|---|
| 305 | 295 | { |
|---|
| 306 | 296 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| .. | .. |
|---|
| 310 | 300 | DIV_FROM_REG(data->fan_div[nr]))); |
|---|
| 311 | 301 | } |
|---|
| 312 | 302 | |
|---|
| 313 | | -static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, |
|---|
| 303 | +static ssize_t fan_min_show(struct device *dev, struct device_attribute *da, |
|---|
| 314 | 304 | char *buf) |
|---|
| 315 | 305 | { |
|---|
| 316 | 306 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| .. | .. |
|---|
| 320 | 310 | DIV_FROM_REG(data->fan_div[nr]))); |
|---|
| 321 | 311 | } |
|---|
| 322 | 312 | |
|---|
| 323 | | -static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, |
|---|
| 324 | | - const char *buf, size_t count) |
|---|
| 313 | +static ssize_t fan_min_store(struct device *dev, struct device_attribute *da, |
|---|
| 314 | + const char *buf, size_t count) |
|---|
| 325 | 315 | { |
|---|
| 326 | 316 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| 327 | 317 | struct lm78_data *data = dev_get_drvdata(dev); |
|---|
| .. | .. |
|---|
| 340 | 330 | return count; |
|---|
| 341 | 331 | } |
|---|
| 342 | 332 | |
|---|
| 343 | | -static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, |
|---|
| 333 | +static ssize_t fan_div_show(struct device *dev, struct device_attribute *da, |
|---|
| 344 | 334 | char *buf) |
|---|
| 345 | 335 | { |
|---|
| 346 | 336 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| .. | .. |
|---|
| 354 | 344 | * least surprise; the user doesn't expect the fan minimum to change just |
|---|
| 355 | 345 | * because the divisor changed. |
|---|
| 356 | 346 | */ |
|---|
| 357 | | -static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, |
|---|
| 358 | | - const char *buf, size_t count) |
|---|
| 347 | +static ssize_t fan_div_store(struct device *dev, struct device_attribute *da, |
|---|
| 348 | + const char *buf, size_t count) |
|---|
| 359 | 349 | { |
|---|
| 360 | 350 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
|---|
| 361 | 351 | struct lm78_data *data = dev_get_drvdata(dev); |
|---|
| .. | .. |
|---|
| 413 | 403 | return count; |
|---|
| 414 | 404 | } |
|---|
| 415 | 405 | |
|---|
| 416 | | -#define show_fan_offset(offset) \ |
|---|
| 417 | | -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
|---|
| 418 | | - show_fan, NULL, offset - 1); \ |
|---|
| 419 | | -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ |
|---|
| 420 | | - show_fan_min, set_fan_min, offset - 1); |
|---|
| 421 | | - |
|---|
| 422 | | -show_fan_offset(1); |
|---|
| 423 | | -show_fan_offset(2); |
|---|
| 424 | | -show_fan_offset(3); |
|---|
| 406 | +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); |
|---|
| 407 | +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); |
|---|
| 408 | +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); |
|---|
| 409 | +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); |
|---|
| 410 | +static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2); |
|---|
| 411 | +static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2); |
|---|
| 425 | 412 | |
|---|
| 426 | 413 | /* Fan 3 divisor is locked in H/W */ |
|---|
| 427 | | -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
|---|
| 428 | | - show_fan_div, set_fan_div, 0); |
|---|
| 429 | | -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, |
|---|
| 430 | | - show_fan_div, set_fan_div, 1); |
|---|
| 431 | | -static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2); |
|---|
| 414 | +static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0); |
|---|
| 415 | +static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1); |
|---|
| 416 | +static SENSOR_DEVICE_ATTR_RO(fan3_div, fan_div, 2); |
|---|
| 432 | 417 | |
|---|
| 433 | 418 | /* VID */ |
|---|
| 434 | 419 | static ssize_t cpu0_vid_show(struct device *dev, struct device_attribute *da, |
|---|
| .. | .. |
|---|
| 448 | 433 | } |
|---|
| 449 | 434 | static DEVICE_ATTR_RO(alarms); |
|---|
| 450 | 435 | |
|---|
| 451 | | -static ssize_t show_alarm(struct device *dev, struct device_attribute *da, |
|---|
| 436 | +static ssize_t alarm_show(struct device *dev, struct device_attribute *da, |
|---|
| 452 | 437 | char *buf) |
|---|
| 453 | 438 | { |
|---|
| 454 | 439 | struct lm78_data *data = lm78_update_device(dev); |
|---|
| 455 | 440 | int nr = to_sensor_dev_attr(da)->index; |
|---|
| 456 | 441 | return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); |
|---|
| 457 | 442 | } |
|---|
| 458 | | -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); |
|---|
| 459 | | -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); |
|---|
| 460 | | -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); |
|---|
| 461 | | -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); |
|---|
| 462 | | -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); |
|---|
| 463 | | -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); |
|---|
| 464 | | -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); |
|---|
| 465 | | -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); |
|---|
| 466 | | -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); |
|---|
| 467 | | -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); |
|---|
| 468 | | -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); |
|---|
| 443 | +static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); |
|---|
| 444 | +static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); |
|---|
| 445 | +static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); |
|---|
| 446 | +static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); |
|---|
| 447 | +static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8); |
|---|
| 448 | +static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 9); |
|---|
| 449 | +static SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 10); |
|---|
| 450 | +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6); |
|---|
| 451 | +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7); |
|---|
| 452 | +static SENSOR_DEVICE_ATTR_RO(fan3_alarm, alarm, 11); |
|---|
| 453 | +static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4); |
|---|
| 469 | 454 | |
|---|
| 470 | 455 | static struct attribute *lm78_attrs[] = { |
|---|
| 471 | 456 | &sensor_dev_attr_in0_input.dev_attr.attr, |
|---|
| .. | .. |
|---|
| 642 | 627 | return -ENODEV; |
|---|
| 643 | 628 | } |
|---|
| 644 | 629 | |
|---|
| 645 | | -static int lm78_i2c_probe(struct i2c_client *client, |
|---|
| 646 | | - const struct i2c_device_id *id) |
|---|
| 630 | +static const struct i2c_device_id lm78_i2c_id[]; |
|---|
| 631 | + |
|---|
| 632 | +static int lm78_i2c_probe(struct i2c_client *client) |
|---|
| 647 | 633 | { |
|---|
| 648 | 634 | struct device *dev = &client->dev; |
|---|
| 649 | 635 | struct device *hwmon_dev; |
|---|
| .. | .. |
|---|
| 654 | 640 | return -ENOMEM; |
|---|
| 655 | 641 | |
|---|
| 656 | 642 | data->client = client; |
|---|
| 657 | | - data->type = id->driver_data; |
|---|
| 643 | + data->type = i2c_match_id(lm78_i2c_id, client)->driver_data; |
|---|
| 658 | 644 | |
|---|
| 659 | 645 | /* Initialize the LM78 chip */ |
|---|
| 660 | 646 | lm78_init_device(data); |
|---|
| .. | .. |
|---|
| 676 | 662 | .driver = { |
|---|
| 677 | 663 | .name = "lm78", |
|---|
| 678 | 664 | }, |
|---|
| 679 | | - .probe = lm78_i2c_probe, |
|---|
| 665 | + .probe_new = lm78_i2c_probe, |
|---|
| 680 | 666 | .id_table = lm78_i2c_id, |
|---|
| 681 | 667 | .detect = lm78_i2c_detect, |
|---|
| 682 | 668 | .address_list = normal_i2c, |
|---|