27 #include <linux/module.h>
29 #include <linux/slab.h>
30 #include <linux/i2c.h>
39 static const unsigned short normal_i2c[] = { 0x2e, 0x2f,
I2C_CLIENT_END };
47 #define W83L786NG_REG_IN_MIN(nr) (0x2C + (nr) * 2)
48 #define W83L786NG_REG_IN_MAX(nr) (0x2B + (nr) * 2)
49 #define W83L786NG_REG_IN(nr) ((nr) + 0x20)
51 #define W83L786NG_REG_FAN(nr) ((nr) + 0x28)
52 #define W83L786NG_REG_FAN_MIN(nr) ((nr) + 0x3B)
54 #define W83L786NG_REG_CONFIG 0x40
55 #define W83L786NG_REG_ALARM1 0x41
56 #define W83L786NG_REG_ALARM2 0x42
57 #define W83L786NG_REG_GPIO_EN 0x47
58 #define W83L786NG_REG_MAN_ID2 0x4C
59 #define W83L786NG_REG_MAN_ID1 0x4D
60 #define W83L786NG_REG_CHIP_ID 0x4E
62 #define W83L786NG_REG_DIODE 0x53
63 #define W83L786NG_REG_FAN_DIV 0x54
64 #define W83L786NG_REG_FAN_CFG 0x80
66 #define W83L786NG_REG_TOLERANCE 0x8D
68 static const u8 W83L786NG_REG_TEMP[2][3] = {
77 static const u8 W83L786NG_PWM_MODE_SHIFT[] = {6, 7};
78 static const u8 W83L786NG_PWM_ENABLE_SHIFT[] = {2, 4};
81 static const u8 W83L786NG_REG_PWM[] = {0x81, 0x87};
89 rpm = SENSORS_LIMIT(rpm, 1, 1000000);
90 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
93 #define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
95 1350000 / ((val) * (div))))
98 #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? \
99 (val) + 0x100 * 1000 \
100 : (val)) / 1000, 0, 0xff))
101 #define TEMP_FROM_REG(val) (((val) & 0x80 ? \
102 (val) - 0x100 : (val)) * 1000)
109 #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 4) / 8), 0, 255))
110 #define IN_FROM_REG(val) ((val) * 8)
112 #define DIV_FROM_REG(val) (1 << (val))
118 val = SENSORS_LIMIT(val, 1, 128) >> 1;
119 for (i = 0; i < 7; i++) {
171 .probe = w83l786ng_probe,
172 .remove = w83l786ng_remove,
173 .id_table = w83l786ng_id,
174 .detect = w83l786ng_detect,
175 .address_list = normal_i2c,
191 #define show_in_reg(reg) \
193 show_##reg(struct device *dev, struct device_attribute *attr, \
196 int nr = to_sensor_dev_attr(attr)->index; \
197 struct w83l786ng_data *data = w83l786ng_update_device(dev); \
198 return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
205 #define store_in_reg(REG, reg) \
207 store_in_##reg(struct device *dev, struct device_attribute *attr, \
208 const char *buf, size_t count) \
210 int nr = to_sensor_dev_attr(attr)->index; \
211 struct i2c_client *client = to_i2c_client(dev); \
212 struct w83l786ng_data *data = i2c_get_clientdata(client); \
214 int err = kstrtoul(buf, 10, &val); \
217 mutex_lock(&data->update_lock); \
218 data->in_##reg[nr] = IN_TO_REG(val); \
219 w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \
220 data->in_##reg[nr]); \
221 mutex_unlock(&data->update_lock); \
246 #define show_fan_reg(reg) \
247 static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
250 int nr = to_sensor_dev_attr(attr)->index; \
251 struct w83l786ng_data *data = w83l786ng_update_device(dev); \
252 return sprintf(buf, "%d\n", \
253 FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \
269 err = kstrtoul(buf, 10, &val);
299 const char *buf,
size_t count)
314 err = kstrtoul(buf, 10, &val);
338 tmp_fan_div = (data->
fan_div[
nr] << new_shift) & ~keep_mask;
341 fan_div_reg | tmp_fan_div);
379 int nr = sensor_attr->
nr;
387 const char *buf,
size_t count)
391 int nr = sensor_attr->
nr;
392 int index = sensor_attr->
index;
398 err = kstrtol(buf, 10, &val);
404 w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index],
405 data->
temp[nr][index]);
430 #define show_pwm_reg(reg) \
431 static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
434 struct w83l786ng_data *data = w83l786ng_update_device(dev); \
435 int nr = to_sensor_dev_attr(attr)->index; \
436 return sprintf(buf, "%d\n", data->reg[nr]); \
445 const char *buf,
size_t count)
454 err = kstrtoul(buf, 10, &val);
463 reg &= ~(1 << W83L786NG_PWM_MODE_SHIFT[
nr]);
465 reg |= 1 << W83L786NG_PWM_MODE_SHIFT[
nr];
473 const char *buf,
size_t count)
481 err = kstrtoul(buf, 10, &val);
484 val = SENSORS_LIMIT(val, 0, 255);
488 w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val);
495 const char *buf,
size_t count)
504 err = kstrtoul(buf, 10, &val);
514 reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[
nr]);
515 reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr];
535 store_pwm_enable, 0),
537 store_pwm_enable, 1),
551 const char *buf,
size_t count)
556 u8 tol_tmp, tol_mask;
560 err = kstrtoul(buf, 10, &val);
565 tol_mask = w83l786ng_read_value(client,
567 tol_tmp = SENSORS_LIMIT(val, 0, 15);
581 show_tolerance, store_tolerance, 0),
583 show_tolerance, store_tolerance, 1),
587 #define IN_UNIT_ATTRS(X) \
588 &sda_in_input[X].dev_attr.attr, \
589 &sda_in_min[X].dev_attr.attr, \
590 &sda_in_max[X].dev_attr.attr
592 #define FAN_UNIT_ATTRS(X) \
593 &sda_fan_input[X].dev_attr.attr, \
594 &sda_fan_min[X].dev_attr.attr, \
595 &sda_fan_div[X].dev_attr.attr
597 #define TEMP_UNIT_ATTRS(X) \
598 &sda_temp_input[X].dev_attr.attr, \
599 &sda_temp_max[X].dev_attr.attr, \
600 &sda_temp_max_hyst[X].dev_attr.attr
602 #define PWM_UNIT_ATTRS(X) \
603 &sda_pwm[X].dev_attr.attr, \
604 &sda_pwm_mode[X].dev_attr.attr, \
605 &sda_pwm_enable[X].dev_attr.attr
607 #define TOLERANCE_UNIT_ATTRS(X) \
608 &sda_tolerance[X].dev_attr.attr
610 static struct attribute *w83l786ng_attributes[] = {
626 .attrs = w83l786ng_attributes,
641 dev_dbg(&adapter->
dev,
"W83L786NG detection failed at 0x%02x\n",
651 if (man_id != 0x5CA3 ||
654 "Unsupported chip (man_id=0x%04X, chip_id=0x%02X)\n",
677 i2c_set_clientdata(client, data);
681 w83l786ng_init_client(client);
684 for (i = 0; i < 2; i++) {
685 data->
fan_min[
i] = w83l786ng_read_value(client,
691 data->
fan_div[0] = reg_tmp & 0x07;
692 data->
fan_div[1] = (reg_tmp >> 4) & 0x07;
726 w83l786ng_init_client(
struct i2c_client *client)
749 dev_dbg(&client->
dev,
"Updating w83l786ng data.\n");
752 for (i = 0; i < 3; i++) {
753 data->
in[
i] = w83l786ng_read_value(client,
755 data->
in_min[
i] = w83l786ng_read_value(client,
757 data->
in_max[
i] = w83l786ng_read_value(client,
762 for (i = 0; i < 2; i++) {
763 data->
fan[
i] = w83l786ng_read_value(client,
765 data->
fan_min[
i] = w83l786ng_read_value(client,
771 data->
fan_div[0] = reg_tmp & 0x07;
772 data->
fan_div[1] = (reg_tmp >> 4) & 0x07;
775 for (i = 0; i < 2; i++) {
777 ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[
i]) & 1)
780 ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[
i]) & 2) + 1;
781 data->
pwm[
i] = w83l786ng_read_value(client,
782 W83L786NG_REG_PWM[i]);
787 for (i = 0; i < 2; i++) {
788 for (j = 0; j < 3; j++) {
789 data->
temp[
i][
j] = w83l786ng_read_value(client,
790 W83L786NG_REG_TEMP[i][j]);
797 data->
tolerance[1] = (reg_tmp >> 4) & 0x0f;