Lines Matching +full:reg +full:- +full:data
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * nct6683 - Driver for the hardware monitoring functionality of
6 * Copyright (C) 2013 Guenter Roeck <linux@roeck-us.net>
9 * Copyright (C) 2012, 2013 Guenter Roeck <linux@roeck-us.net>
31 #include <linux/hwmon-sysfs.h>
58 * Super-I/O constants and functions
77 superio_outb(int ioreg, int reg, int val) in superio_outb() argument
79 outb(reg, ioreg); in superio_outb()
84 superio_inb(int ioreg, int reg) in superio_inb() argument
86 outb(reg, ioreg); in superio_inb()
104 return -EBUSY; in superio_enter()
134 /* Common and NCT6683 specific data */
295 /* ------------------------------------------------------- */
417 return ERR_PTR(-EINVAL); in nct6683_create_attr_group()
419 t = tg->templates; in nct6683_create_attr_group()
424 return ERR_PTR(-EINVAL); in nct6683_create_attr_group()
428 return ERR_PTR(-ENOMEM); in nct6683_create_attr_group()
433 return ERR_PTR(-ENOMEM); in nct6683_create_attr_group()
438 return ERR_PTR(-ENOMEM); in nct6683_create_attr_group()
440 group->attrs = attrs; in nct6683_create_attr_group()
441 group->is_visible = tg->is_visible; in nct6683_create_attr_group()
444 t = tg->templates; in nct6683_create_attr_group()
446 snprintf(su->name, sizeof(su->name), in nct6683_create_attr_group()
447 (*t)->dev_attr.attr.name, tg->base + i); in nct6683_create_attr_group()
448 if ((*t)->s2) { in nct6683_create_attr_group()
449 a2 = &su->u.a2; in nct6683_create_attr_group()
450 sysfs_attr_init(&a2->dev_attr.attr); in nct6683_create_attr_group()
451 a2->dev_attr.attr.name = su->name; in nct6683_create_attr_group()
452 a2->nr = (*t)->u.s.nr + i; in nct6683_create_attr_group()
453 a2->index = (*t)->u.s.index; in nct6683_create_attr_group()
454 a2->dev_attr.attr.mode = in nct6683_create_attr_group()
455 (*t)->dev_attr.attr.mode; in nct6683_create_attr_group()
456 a2->dev_attr.show = (*t)->dev_attr.show; in nct6683_create_attr_group()
457 a2->dev_attr.store = (*t)->dev_attr.store; in nct6683_create_attr_group()
458 *attrs = &a2->dev_attr.attr; in nct6683_create_attr_group()
460 a = &su->u.a1; in nct6683_create_attr_group()
461 sysfs_attr_init(&a->dev_attr.attr); in nct6683_create_attr_group()
462 a->dev_attr.attr.name = su->name; in nct6683_create_attr_group()
463 a->index = (*t)->u.index + i; in nct6683_create_attr_group()
464 a->dev_attr.attr.mode = in nct6683_create_attr_group()
465 (*t)->dev_attr.attr.mode; in nct6683_create_attr_group()
466 a->dev_attr.show = (*t)->dev_attr.show; in nct6683_create_attr_group()
467 a->dev_attr.store = (*t)->dev_attr.store; in nct6683_create_attr_group()
468 *attrs = &a->dev_attr.attr; in nct6683_create_attr_group()
485 static inline long in_from_reg(u16 reg, u8 src) in in_from_reg() argument
492 return reg * scale; in in_from_reg()
495 static u16 nct6683_read(struct nct6683_data *data, u16 reg) in nct6683_read() argument
499 outb_p(0xff, data->addr + EC_PAGE_REG); /* unlock */ in nct6683_read()
500 outb_p(reg >> 8, data->addr + EC_PAGE_REG); in nct6683_read()
501 outb_p(reg & 0xff, data->addr + EC_INDEX_REG); in nct6683_read()
502 res = inb_p(data->addr + EC_DATA_REG); in nct6683_read()
506 static u16 nct6683_read16(struct nct6683_data *data, u16 reg) in nct6683_read16() argument
508 return (nct6683_read(data, reg) << 8) | nct6683_read(data, reg + 1); in nct6683_read16()
511 static void nct6683_write(struct nct6683_data *data, u16 reg, u16 value) in nct6683_write() argument
513 outb_p(0xff, data->addr + EC_PAGE_REG); /* unlock */ in nct6683_write()
514 outb_p(reg >> 8, data->addr + EC_PAGE_REG); in nct6683_write()
515 outb_p(reg & 0xff, data->addr + EC_INDEX_REG); in nct6683_write()
516 outb_p(value & 0xff, data->addr + EC_DATA_REG); in nct6683_write()
519 static int get_in_reg(struct nct6683_data *data, int nr, int index) in get_in_reg() argument
521 int ch = data->in_index[index]; in get_in_reg()
522 int reg = -EINVAL; in get_in_reg() local
526 reg = NCT6683_REG_MON(ch); in get_in_reg()
529 if (data->customer_id != NCT6683_CUSTOMER_ID_INTEL) in get_in_reg()
530 reg = NCT6683_REG_MON_LOW(ch); in get_in_reg()
533 if (data->customer_id != NCT6683_CUSTOMER_ID_INTEL) in get_in_reg()
534 reg = NCT6683_REG_MON_HIGH(ch); in get_in_reg()
539 return reg; in get_in_reg()
542 static int get_temp_reg(struct nct6683_data *data, int nr, int index) in get_temp_reg() argument
544 int ch = data->temp_index[index]; in get_temp_reg()
545 int reg = -EINVAL; in get_temp_reg() local
547 switch (data->customer_id) { in get_temp_reg()
552 reg = NCT6683_REG_INTEL_TEMP_MAX(ch); in get_temp_reg()
555 reg = NCT6683_REG_INTEL_TEMP_CRIT(ch); in get_temp_reg()
564 reg = NCT6683_REG_MON_LOW(ch); in get_temp_reg()
567 reg = NCT6683_REG_TEMP_MAX(ch); in get_temp_reg()
570 reg = NCT6683_REG_TEMP_HYST(ch); in get_temp_reg()
573 reg = NCT6683_REG_MON_HIGH(ch); in get_temp_reg()
578 return reg; in get_temp_reg()
583 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_update_pwm() local
587 if (!(data->have_pwm & (1 << i))) in nct6683_update_pwm()
589 data->pwm[i] = nct6683_read(data, NCT6683_REG_PWM(i)); in nct6683_update_pwm()
595 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_update_device() local
598 mutex_lock(&data->update_lock); in nct6683_update_device()
600 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { in nct6683_update_device()
602 for (i = 0; i < data->in_num; i++) { in nct6683_update_device()
604 int reg = get_in_reg(data, j, i); in nct6683_update_device() local
606 if (reg >= 0) in nct6683_update_device()
607 data->in[j][i] = in nct6683_update_device()
608 nct6683_read(data, reg); in nct6683_update_device()
613 for (i = 0; i < data->temp_num; i++) { in nct6683_update_device()
614 u8 ch = data->temp_index[i]; in nct6683_update_device()
616 data->temp_in[i] = nct6683_read16(data, in nct6683_update_device()
619 int reg = get_temp_reg(data, j, i); in nct6683_update_device() local
621 if (reg >= 0) in nct6683_update_device()
622 data->temp[j][i] = in nct6683_update_device()
623 nct6683_read(data, reg); in nct6683_update_device()
628 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) { in nct6683_update_device()
629 if (!(data->have_fan & (1 << i))) in nct6683_update_device()
632 data->rpm[i] = nct6683_read16(data, in nct6683_update_device()
634 data->fan_min[i] = nct6683_read16(data, in nct6683_update_device()
640 data->last_updated = jiffies; in nct6683_update_device()
641 data->valid = true; in nct6683_update_device()
644 mutex_unlock(&data->update_lock); in nct6683_update_device()
645 return data; in nct6683_update_device()
655 struct nct6683_data *data = nct6683_update_device(dev); in show_in_label() local
656 int nr = sattr->index; in show_in_label()
658 return sprintf(buf, "%s\n", nct6683_mon_label[data->in_src[nr]]); in show_in_label()
665 struct nct6683_data *data = nct6683_update_device(dev); in show_in_reg() local
666 int index = sattr->index; in show_in_reg()
667 int nr = sattr->nr; in show_in_reg()
670 in_from_reg(data->in[index][nr], data->in_index[index])); in show_in_reg()
677 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_in_is_visible() local
685 data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_in_is_visible()
688 return attr->mode; in nct6683_in_is_visible()
713 struct nct6683_data *data = nct6683_update_device(dev); in show_fan() local
715 return sprintf(buf, "%d\n", data->rpm[sattr->index]); in show_fan()
721 struct nct6683_data *data = nct6683_update_device(dev); in show_fan_min() local
723 int nr = sattr->index; in show_fan_min()
725 return sprintf(buf, "%d\n", data->fan_min[nr]); in show_fan_min()
732 struct nct6683_data *data = nct6683_update_device(dev); in show_fan_pulses() local
735 ((data->fanin_cfg[sattr->index] >> 5) & 0x03) + 1); in show_fan_pulses()
742 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_fan_is_visible() local
746 if (!(data->have_fan & (1 << fan))) in nct6683_fan_is_visible()
753 if (nr == 2 && data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_fan_is_visible()
756 return attr->mode; in nct6683_fan_is_visible()
785 struct nct6683_data *data = nct6683_update_device(dev); in show_temp_label() local
786 int nr = sattr->index; in show_temp_label()
788 return sprintf(buf, "%s\n", nct6683_mon_label[data->temp_src[nr]]); in show_temp_label()
795 struct nct6683_data *data = nct6683_update_device(dev); in show_temp8() local
796 int index = sattr->index; in show_temp8()
797 int nr = sattr->nr; in show_temp8()
799 return sprintf(buf, "%d\n", data->temp[index][nr] * 1000); in show_temp8()
806 struct nct6683_data *data = nct6683_update_device(dev); in show_temp_hyst() local
807 int nr = sattr->index; in show_temp_hyst()
808 int temp = data->temp[1][nr] - data->temp[2][nr]; in show_temp_hyst()
817 struct nct6683_data *data = nct6683_update_device(dev); in show_temp16() local
818 int index = sattr->index; in show_temp16()
820 return sprintf(buf, "%d\n", (data->temp_in[index] / 128) * 500); in show_temp16()
850 struct nct6683_data *data = nct6683_update_device(dev); in show_temp_type() local
852 int nr = sattr->index; in show_temp_type()
853 return sprintf(buf, "%d\n", get_temp_type(data->temp_src[nr])); in show_temp_type()
860 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_temp_is_visible() local
869 data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_temp_is_visible()
872 if (nr == 6 && get_temp_type(data->temp_src[temp]) == 0) in nct6683_temp_is_visible()
875 return attr->mode; in nct6683_temp_is_visible()
912 struct nct6683_data *data = nct6683_update_device(dev); in show_pwm() local
914 int index = sattr->index; in show_pwm()
916 return sprintf(buf, "%d\n", data->pwm[index]); in show_pwm()
924 struct nct6683_data *data = dev_get_drvdata(dev); in store_pwm() local
925 int index = sattr->index; in store_pwm()
929 return -EINVAL; in store_pwm()
931 mutex_lock(&data->update_lock); in store_pwm()
932 nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_REQ); in store_pwm()
934 nct6683_write(data, NCT6683_REG_PWM_WRITE(index), val); in store_pwm()
935 nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_DONE); in store_pwm()
936 mutex_unlock(&data->update_lock); in store_pwm()
947 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_pwm_is_visible() local
950 if (!(data->have_pwm & (1 << pwm))) in nct6683_pwm_is_visible()
954 if (data->customer_id == NCT6683_CUSTOMER_ID_MITAC) in nct6683_pwm_is_visible()
955 return attr->mode | S_IWUSR; in nct6683_pwm_is_visible()
957 return attr->mode; in nct6683_pwm_is_visible()
974 struct nct6683_data *data = dev_get_drvdata(dev); in beep_enable_show() local
976 u8 reg; in beep_enable_show() local
978 mutex_lock(&data->update_lock); in beep_enable_show()
980 ret = superio_enter(data->sioreg); in beep_enable_show()
983 superio_select(data->sioreg, NCT6683_LD_HWM); in beep_enable_show()
984 reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP); in beep_enable_show()
985 superio_exit(data->sioreg); in beep_enable_show()
987 mutex_unlock(&data->update_lock); in beep_enable_show()
989 return sprintf(buf, "%u\n", !!(reg & NCT6683_CR_BEEP_MASK)); in beep_enable_show()
992 mutex_unlock(&data->update_lock); in beep_enable_show()
1000 struct nct6683_data *data = dev_get_drvdata(dev); in beep_enable_store() local
1002 u8 reg; in beep_enable_store() local
1006 return -EINVAL; in beep_enable_store()
1008 mutex_lock(&data->update_lock); in beep_enable_store()
1010 ret = superio_enter(data->sioreg); in beep_enable_store()
1016 superio_select(data->sioreg, NCT6683_LD_HWM); in beep_enable_store()
1017 reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP); in beep_enable_store()
1019 reg |= NCT6683_CR_BEEP_MASK; in beep_enable_store()
1021 reg &= ~NCT6683_CR_BEEP_MASK; in beep_enable_store()
1022 superio_outb(data->sioreg, NCT6683_REG_CR_BEEP, reg); in beep_enable_store()
1023 superio_exit(data->sioreg); in beep_enable_store()
1025 mutex_unlock(&data->update_lock); in beep_enable_store()
1035 struct nct6683_data *data = dev_get_drvdata(dev); in intrusion0_alarm_show() local
1037 u8 reg; in intrusion0_alarm_show() local
1039 mutex_lock(&data->update_lock); in intrusion0_alarm_show()
1041 ret = superio_enter(data->sioreg); in intrusion0_alarm_show()
1044 superio_select(data->sioreg, NCT6683_LD_ACPI); in intrusion0_alarm_show()
1045 reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN); in intrusion0_alarm_show()
1046 superio_exit(data->sioreg); in intrusion0_alarm_show()
1048 mutex_unlock(&data->update_lock); in intrusion0_alarm_show()
1050 return sprintf(buf, "%u\n", !(reg & NCT6683_CR_CASEOPEN_MASK)); in intrusion0_alarm_show()
1053 mutex_unlock(&data->update_lock); in intrusion0_alarm_show()
1061 struct nct6683_data *data = dev_get_drvdata(dev); in intrusion0_alarm_store() local
1063 u8 reg; in intrusion0_alarm_store() local
1067 return -EINVAL; in intrusion0_alarm_store()
1069 mutex_lock(&data->update_lock); in intrusion0_alarm_store()
1076 ret = superio_enter(data->sioreg); in intrusion0_alarm_store()
1082 superio_select(data->sioreg, NCT6683_LD_ACPI); in intrusion0_alarm_store()
1083 reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN); in intrusion0_alarm_store()
1084 reg |= NCT6683_CR_CASEOPEN_MASK; in intrusion0_alarm_store()
1085 superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg); in intrusion0_alarm_store()
1086 reg &= ~NCT6683_CR_CASEOPEN_MASK; in intrusion0_alarm_store()
1087 superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg); in intrusion0_alarm_store()
1088 superio_exit(data->sioreg); in intrusion0_alarm_store()
1090 data->valid = false; /* Force cache refresh */ in intrusion0_alarm_store()
1092 mutex_unlock(&data->update_lock); in intrusion0_alarm_store()
1110 static inline void nct6683_init_device(struct nct6683_data *data) in nct6683_init_device() argument
1115 tmp = nct6683_read(data, NCT6683_HWM_CFG); in nct6683_init_device()
1117 nct6683_write(data, NCT6683_HWM_CFG, tmp | 0x80); in nct6683_init_device()
1125 nct6683_setup_fans(struct nct6683_data *data) in nct6683_setup_fans() argument
1128 u8 reg; in nct6683_setup_fans() local
1131 reg = nct6683_read(data, NCT6683_REG_FANIN_CFG(i)); in nct6683_setup_fans()
1132 if (reg & 0x80) in nct6683_setup_fans()
1133 data->have_fan |= 1 << i; in nct6683_setup_fans()
1134 data->fanin_cfg[i] = reg; in nct6683_setup_fans()
1137 reg = nct6683_read(data, NCT6683_REG_FANOUT_CFG(i)); in nct6683_setup_fans()
1138 if (reg & 0x80) in nct6683_setup_fans()
1139 data->have_pwm |= 1 << i; in nct6683_setup_fans()
1140 data->fanout_cfg[i] = reg; in nct6683_setup_fans()
1160 static void nct6683_setup_sensors(struct nct6683_data *data) in nct6683_setup_sensors() argument
1162 u8 reg; in nct6683_setup_sensors() local
1165 data->temp_num = 0; in nct6683_setup_sensors()
1166 data->in_num = 0; in nct6683_setup_sensors()
1168 reg = nct6683_read(data, NCT6683_REG_MON_CFG(i)) & 0x7f; in nct6683_setup_sensors()
1170 if (reg >= NUM_MON_LABELS) in nct6683_setup_sensors()
1173 if (nct6683_mon_label[reg] == NULL) in nct6683_setup_sensors()
1175 if (reg < MON_VOLTAGE_START) { in nct6683_setup_sensors()
1176 data->temp_index[data->temp_num] = i; in nct6683_setup_sensors()
1177 data->temp_src[data->temp_num] = reg; in nct6683_setup_sensors()
1178 data->temp_num++; in nct6683_setup_sensors()
1180 data->in_index[data->in_num] = i; in nct6683_setup_sensors()
1181 data->in_src[data->in_num] = reg; in nct6683_setup_sensors()
1182 data->in_num++; in nct6683_setup_sensors()
1189 struct device *dev = &pdev->dev; in nct6683_probe()
1190 struct nct6683_sio_data *sio_data = dev->platform_data; in nct6683_probe()
1192 struct nct6683_data *data; in nct6683_probe() local
1199 if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME)) in nct6683_probe()
1200 return -EBUSY; in nct6683_probe()
1202 data = devm_kzalloc(dev, sizeof(struct nct6683_data), GFP_KERNEL); in nct6683_probe()
1203 if (!data) in nct6683_probe()
1204 return -ENOMEM; in nct6683_probe()
1206 data->kind = sio_data->kind; in nct6683_probe()
1207 data->sioreg = sio_data->sioreg; in nct6683_probe()
1208 data->addr = res->start; in nct6683_probe()
1209 mutex_init(&data->update_lock); in nct6683_probe()
1210 platform_set_drvdata(pdev, data); in nct6683_probe()
1212 data->customer_id = nct6683_read16(data, NCT6683_REG_CUSTOMER_ID); in nct6683_probe()
1215 switch (data->customer_id) { in nct6683_probe()
1226 return -ENODEV; in nct6683_probe()
1229 nct6683_init_device(data); in nct6683_probe()
1230 nct6683_setup_fans(data); in nct6683_probe()
1231 nct6683_setup_sensors(data); in nct6683_probe()
1235 if (data->have_pwm) { in nct6683_probe()
1238 fls(data->have_pwm)); in nct6683_probe()
1241 data->groups[groups++] = group; in nct6683_probe()
1244 if (data->in_num) { in nct6683_probe()
1247 data->in_num); in nct6683_probe()
1250 data->groups[groups++] = group; in nct6683_probe()
1253 if (data->have_fan) { in nct6683_probe()
1256 fls(data->have_fan)); in nct6683_probe()
1259 data->groups[groups++] = group; in nct6683_probe()
1262 if (data->temp_num) { in nct6683_probe()
1265 data->temp_num); in nct6683_probe()
1268 data->groups[groups++] = group; in nct6683_probe()
1270 data->groups[groups++] = &nct6683_group_other; in nct6683_probe()
1272 if (data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_probe()
1274 nct6683_read(data, NCT6683_REG_BUILD_MONTH), in nct6683_probe()
1275 nct6683_read(data, NCT6683_REG_BUILD_DAY), in nct6683_probe()
1276 nct6683_read(data, NCT6683_REG_BUILD_YEAR)); in nct6683_probe()
1279 nct6683_read(data, NCT6683_REG_BUILD_MONTH), in nct6683_probe()
1280 nct6683_read(data, NCT6683_REG_BUILD_DAY), in nct6683_probe()
1281 nct6683_read(data, NCT6683_REG_BUILD_YEAR)); in nct6683_probe()
1284 nct6683_chip_names[data->kind], in nct6683_probe()
1285 nct6683_read(data, NCT6683_REG_VERSION_HI), in nct6683_probe()
1286 nct6683_read(data, NCT6683_REG_VERSION_LO), in nct6683_probe()
1290 nct6683_device_names[data->kind], data, data->groups); in nct6683_probe()
1297 struct nct6683_data *data = nct6683_update_device(dev); in nct6683_suspend() local
1299 mutex_lock(&data->update_lock); in nct6683_suspend()
1300 data->hwm_cfg = nct6683_read(data, NCT6683_HWM_CFG); in nct6683_suspend()
1301 mutex_unlock(&data->update_lock); in nct6683_suspend()
1308 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_resume() local
1310 mutex_lock(&data->update_lock); in nct6683_resume()
1312 nct6683_write(data, NCT6683_HWM_CFG, data->hwm_cfg); in nct6683_resume()
1314 /* Force re-reading all values */ in nct6683_resume()
1315 data->valid = false; in nct6683_resume()
1316 mutex_unlock(&data->update_lock); in nct6683_resume()
1356 sio_data->kind = nct6683; in nct6683_find()
1359 sio_data->kind = nct6686; in nct6683_find()
1362 sio_data->kind = nct6687; in nct6683_find()
1383 pr_warn("Forcibly enabling EC access. Data may be unusable.\n"); in nct6683_find()
1389 nct6683_chip_names[sio_data->kind], sioaddr, addr); in nct6683_find()
1390 sio_data->sioreg = sioaddr; in nct6683_find()
1396 return -ENODEV; in nct6683_find()
1400 * when Super-I/O functions move to a separate file, the Super-I/O
1421 * initialize sio_data->kind and sio_data->sioreg. in sensors_nct6683_init()
1423 * when Super-I/O functions move to a separate file, the Super-I/O in sensors_nct6683_init()
1424 * driver will probe 0x2e and 0x4e and auto-detect the presence of a in sensors_nct6683_init()
1436 err = -ENOMEM; in sensors_nct6683_init()
1448 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; in sensors_nct6683_init()
1468 err = -ENODEV; in sensors_nct6683_init()
1477 while (--i >= 0) { in sensors_nct6683_init()
1497 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");