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>
29 #include <linux/hwmon-sysfs.h>
52 * Super-I/O constants and functions
69 superio_outb(int ioreg, int reg, int val) in superio_outb() argument
71 outb(reg, ioreg); in superio_outb()
76 superio_inb(int ioreg, int reg) in superio_inb() argument
78 outb(reg, ioreg); in superio_inb()
96 return -EBUSY; in superio_enter()
126 /* Common and NCT6683 specific data */
285 /* ------------------------------------------------------- */
407 return ERR_PTR(-EINVAL); in nct6683_create_attr_group()
409 t = tg->templates; in nct6683_create_attr_group()
414 return ERR_PTR(-EINVAL); in nct6683_create_attr_group()
418 return ERR_PTR(-ENOMEM); in nct6683_create_attr_group()
423 return ERR_PTR(-ENOMEM); in nct6683_create_attr_group()
428 return ERR_PTR(-ENOMEM); in nct6683_create_attr_group()
430 group->attrs = attrs; in nct6683_create_attr_group()
431 group->is_visible = tg->is_visible; in nct6683_create_attr_group()
434 t = tg->templates; in nct6683_create_attr_group()
436 snprintf(su->name, sizeof(su->name), in nct6683_create_attr_group()
437 (*t)->dev_attr.attr.name, tg->base + i); in nct6683_create_attr_group()
438 if ((*t)->s2) { in nct6683_create_attr_group()
439 a2 = &su->u.a2; in nct6683_create_attr_group()
440 sysfs_attr_init(&a2->dev_attr.attr); in nct6683_create_attr_group()
441 a2->dev_attr.attr.name = su->name; in nct6683_create_attr_group()
442 a2->nr = (*t)->u.s.nr + i; in nct6683_create_attr_group()
443 a2->index = (*t)->u.s.index; in nct6683_create_attr_group()
444 a2->dev_attr.attr.mode = in nct6683_create_attr_group()
445 (*t)->dev_attr.attr.mode; in nct6683_create_attr_group()
446 a2->dev_attr.show = (*t)->dev_attr.show; in nct6683_create_attr_group()
447 a2->dev_attr.store = (*t)->dev_attr.store; in nct6683_create_attr_group()
448 *attrs = &a2->dev_attr.attr; in nct6683_create_attr_group()
450 a = &su->u.a1; in nct6683_create_attr_group()
451 sysfs_attr_init(&a->dev_attr.attr); in nct6683_create_attr_group()
452 a->dev_attr.attr.name = su->name; in nct6683_create_attr_group()
453 a->index = (*t)->u.index + i; in nct6683_create_attr_group()
454 a->dev_attr.attr.mode = in nct6683_create_attr_group()
455 (*t)->dev_attr.attr.mode; in nct6683_create_attr_group()
456 a->dev_attr.show = (*t)->dev_attr.show; in nct6683_create_attr_group()
457 a->dev_attr.store = (*t)->dev_attr.store; in nct6683_create_attr_group()
458 *attrs = &a->dev_attr.attr; in nct6683_create_attr_group()
475 static inline long in_from_reg(u16 reg, u8 src) in in_from_reg() argument
482 return reg * scale; in in_from_reg()
496 static u16 nct6683_read(struct nct6683_data *data, u16 reg) in nct6683_read() argument
500 outb_p(0xff, data->addr + EC_PAGE_REG); /* unlock */ in nct6683_read()
501 outb_p(reg >> 8, data->addr + EC_PAGE_REG); in nct6683_read()
502 outb_p(reg & 0xff, data->addr + EC_INDEX_REG); in nct6683_read()
503 res = inb_p(data->addr + EC_DATA_REG); in nct6683_read()
507 static u16 nct6683_read16(struct nct6683_data *data, u16 reg) in nct6683_read16() argument
509 return (nct6683_read(data, reg) << 8) | nct6683_read(data, reg + 1); in nct6683_read16()
512 static void nct6683_write(struct nct6683_data *data, u16 reg, u16 value) in nct6683_write() argument
514 outb_p(0xff, data->addr + EC_PAGE_REG); /* unlock */ in nct6683_write()
515 outb_p(reg >> 8, data->addr + EC_PAGE_REG); in nct6683_write()
516 outb_p(reg & 0xff, data->addr + EC_INDEX_REG); in nct6683_write()
517 outb_p(value & 0xff, data->addr + EC_DATA_REG); in nct6683_write()
520 static int get_in_reg(struct nct6683_data *data, int nr, int index) in get_in_reg() argument
522 int ch = data->in_index[index]; in get_in_reg()
523 int reg = -EINVAL; in get_in_reg() local
527 reg = NCT6683_REG_MON(ch); in get_in_reg()
530 if (data->customer_id != NCT6683_CUSTOMER_ID_INTEL) in get_in_reg()
531 reg = NCT6683_REG_MON_LOW(ch); in get_in_reg()
534 if (data->customer_id != NCT6683_CUSTOMER_ID_INTEL) in get_in_reg()
535 reg = NCT6683_REG_MON_HIGH(ch); in get_in_reg()
540 return reg; in get_in_reg()
543 static int get_temp_reg(struct nct6683_data *data, int nr, int index) in get_temp_reg() argument
545 int ch = data->temp_index[index]; in get_temp_reg()
546 int reg = -EINVAL; in get_temp_reg() local
548 switch (data->customer_id) { in get_temp_reg()
553 reg = NCT6683_REG_INTEL_TEMP_MAX(ch); in get_temp_reg()
556 reg = NCT6683_REG_INTEL_TEMP_CRIT(ch); in get_temp_reg()
565 reg = NCT6683_REG_MON_LOW(ch); in get_temp_reg()
568 reg = NCT6683_REG_TEMP_MAX(ch); in get_temp_reg()
571 reg = NCT6683_REG_TEMP_HYST(ch); in get_temp_reg()
574 reg = NCT6683_REG_MON_HIGH(ch); in get_temp_reg()
579 return reg; in get_temp_reg()
584 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_update_pwm() local
588 if (!(data->have_pwm & (1 << i))) in nct6683_update_pwm()
590 data->pwm[i] = nct6683_read(data, NCT6683_REG_PWM(i)); in nct6683_update_pwm()
596 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_update_device() local
599 mutex_lock(&data->update_lock); in nct6683_update_device()
601 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { in nct6683_update_device()
603 for (i = 0; i < data->in_num; i++) { in nct6683_update_device()
605 int reg = get_in_reg(data, j, i); in nct6683_update_device() local
607 if (reg >= 0) in nct6683_update_device()
608 data->in[j][i] = in nct6683_update_device()
609 nct6683_read(data, reg); in nct6683_update_device()
614 for (i = 0; i < data->temp_num; i++) { in nct6683_update_device()
615 u8 ch = data->temp_index[i]; in nct6683_update_device()
617 data->temp_in[i] = nct6683_read16(data, in nct6683_update_device()
620 int reg = get_temp_reg(data, j, i); in nct6683_update_device() local
622 if (reg >= 0) in nct6683_update_device()
623 data->temp[j][i] = in nct6683_update_device()
624 nct6683_read(data, reg); in nct6683_update_device()
629 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) { in nct6683_update_device()
630 if (!(data->have_fan & (1 << i))) in nct6683_update_device()
633 data->rpm[i] = nct6683_read16(data, in nct6683_update_device()
635 data->fan_min[i] = nct6683_read16(data, in nct6683_update_device()
641 data->last_updated = jiffies; in nct6683_update_device()
642 data->valid = true; in nct6683_update_device()
645 mutex_unlock(&data->update_lock); in nct6683_update_device()
646 return data; in nct6683_update_device()
656 struct nct6683_data *data = nct6683_update_device(dev); in show_in_label() local
657 int nr = sattr->index; in show_in_label()
659 return sprintf(buf, "%s\n", nct6683_mon_label[data->in_src[nr]]); in show_in_label()
666 struct nct6683_data *data = nct6683_update_device(dev); in show_in_reg() local
667 int index = sattr->index; in show_in_reg()
668 int nr = sattr->nr; in show_in_reg()
671 in_from_reg(data->in[index][nr], data->in_index[index])); in show_in_reg()
678 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_in_is_visible() local
686 data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_in_is_visible()
689 return attr->mode; in nct6683_in_is_visible()
714 struct nct6683_data *data = nct6683_update_device(dev); in show_fan() local
716 return sprintf(buf, "%d\n", data->rpm[sattr->index]); in show_fan()
722 struct nct6683_data *data = nct6683_update_device(dev); in show_fan_min() local
724 int nr = sattr->index; in show_fan_min()
726 return sprintf(buf, "%d\n", data->fan_min[nr]); in show_fan_min()
733 struct nct6683_data *data = nct6683_update_device(dev); in show_fan_pulses() local
736 ((data->fanin_cfg[sattr->index] >> 5) & 0x03) + 1); in show_fan_pulses()
743 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_fan_is_visible() local
747 if (!(data->have_fan & (1 << fan))) in nct6683_fan_is_visible()
754 if (nr == 2 && data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_fan_is_visible()
757 return attr->mode; in nct6683_fan_is_visible()
786 struct nct6683_data *data = nct6683_update_device(dev); in show_temp_label() local
787 int nr = sattr->index; in show_temp_label()
789 return sprintf(buf, "%s\n", nct6683_mon_label[data->temp_src[nr]]); in show_temp_label()
796 struct nct6683_data *data = nct6683_update_device(dev); in show_temp8() local
797 int index = sattr->index; in show_temp8()
798 int nr = sattr->nr; in show_temp8()
800 return sprintf(buf, "%d\n", data->temp[index][nr] * 1000); in show_temp8()
807 struct nct6683_data *data = nct6683_update_device(dev); in show_temp_hyst() local
808 int nr = sattr->index; in show_temp_hyst()
809 int temp = data->temp[1][nr] - data->temp[2][nr]; in show_temp_hyst()
818 struct nct6683_data *data = nct6683_update_device(dev); in show_temp16() local
819 int index = sattr->index; in show_temp16()
821 return sprintf(buf, "%d\n", (data->temp_in[index] / 128) * 500); in show_temp16()
851 struct nct6683_data *data = nct6683_update_device(dev); in show_temp_type() local
853 int nr = sattr->index; in show_temp_type()
854 return sprintf(buf, "%d\n", get_temp_type(data->temp_src[nr])); in show_temp_type()
861 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_temp_is_visible() local
870 data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_temp_is_visible()
873 if (nr == 6 && get_temp_type(data->temp_src[temp]) == 0) in nct6683_temp_is_visible()
876 return attr->mode; in nct6683_temp_is_visible()
913 struct nct6683_data *data = nct6683_update_device(dev); in show_pwm() local
915 int index = sattr->index; in show_pwm()
917 return sprintf(buf, "%d\n", data->pwm[index]); in show_pwm()
925 struct nct6683_data *data = dev_get_drvdata(dev); in store_pwm() local
926 int index = sattr->index; in store_pwm()
930 return -EINVAL; in store_pwm()
932 mutex_lock(&data->update_lock); in store_pwm()
933 nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_REQ); in store_pwm()
935 nct6683_write(data, NCT6683_REG_PWM_WRITE(index), val); in store_pwm()
936 nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_DONE); in store_pwm()
937 mutex_unlock(&data->update_lock); in store_pwm()
948 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_pwm_is_visible() local
951 if (!(data->have_pwm & (1 << pwm))) in nct6683_pwm_is_visible()
955 if (data->customer_id == NCT6683_CUSTOMER_ID_MITAC) in nct6683_pwm_is_visible()
956 return attr->mode | S_IWUSR; in nct6683_pwm_is_visible()
958 return attr->mode; in nct6683_pwm_is_visible()
975 struct nct6683_data *data = dev_get_drvdata(dev); in beep_enable_show() local
977 u8 reg; in beep_enable_show() local
979 mutex_lock(&data->update_lock); in beep_enable_show()
981 ret = superio_enter(data->sioreg); in beep_enable_show()
984 superio_select(data->sioreg, NCT6683_LD_HWM); in beep_enable_show()
985 reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP); in beep_enable_show()
986 superio_exit(data->sioreg); in beep_enable_show()
988 mutex_unlock(&data->update_lock); in beep_enable_show()
990 return sprintf(buf, "%u\n", !!(reg & NCT6683_CR_BEEP_MASK)); in beep_enable_show()
993 mutex_unlock(&data->update_lock); in beep_enable_show()
1001 struct nct6683_data *data = dev_get_drvdata(dev); in beep_enable_store() local
1003 u8 reg; in beep_enable_store() local
1007 return -EINVAL; in beep_enable_store()
1009 mutex_lock(&data->update_lock); in beep_enable_store()
1011 ret = superio_enter(data->sioreg); in beep_enable_store()
1017 superio_select(data->sioreg, NCT6683_LD_HWM); in beep_enable_store()
1018 reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP); in beep_enable_store()
1020 reg |= NCT6683_CR_BEEP_MASK; in beep_enable_store()
1022 reg &= ~NCT6683_CR_BEEP_MASK; in beep_enable_store()
1023 superio_outb(data->sioreg, NCT6683_REG_CR_BEEP, reg); in beep_enable_store()
1024 superio_exit(data->sioreg); in beep_enable_store()
1026 mutex_unlock(&data->update_lock); in beep_enable_store()
1036 struct nct6683_data *data = dev_get_drvdata(dev); in intrusion0_alarm_show() local
1038 u8 reg; in intrusion0_alarm_show() local
1040 mutex_lock(&data->update_lock); in intrusion0_alarm_show()
1042 ret = superio_enter(data->sioreg); in intrusion0_alarm_show()
1045 superio_select(data->sioreg, NCT6683_LD_ACPI); in intrusion0_alarm_show()
1046 reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN); in intrusion0_alarm_show()
1047 superio_exit(data->sioreg); in intrusion0_alarm_show()
1049 mutex_unlock(&data->update_lock); in intrusion0_alarm_show()
1051 return sprintf(buf, "%u\n", !(reg & NCT6683_CR_CASEOPEN_MASK)); in intrusion0_alarm_show()
1054 mutex_unlock(&data->update_lock); in intrusion0_alarm_show()
1062 struct nct6683_data *data = dev_get_drvdata(dev); in intrusion0_alarm_store() local
1064 u8 reg; in intrusion0_alarm_store() local
1068 return -EINVAL; in intrusion0_alarm_store()
1070 mutex_lock(&data->update_lock); in intrusion0_alarm_store()
1077 ret = superio_enter(data->sioreg); in intrusion0_alarm_store()
1083 superio_select(data->sioreg, NCT6683_LD_ACPI); in intrusion0_alarm_store()
1084 reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN); in intrusion0_alarm_store()
1085 reg |= NCT6683_CR_CASEOPEN_MASK; in intrusion0_alarm_store()
1086 superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg); in intrusion0_alarm_store()
1087 reg &= ~NCT6683_CR_CASEOPEN_MASK; in intrusion0_alarm_store()
1088 superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg); in intrusion0_alarm_store()
1089 superio_exit(data->sioreg); in intrusion0_alarm_store()
1091 data->valid = false; /* Force cache refresh */ in intrusion0_alarm_store()
1093 mutex_unlock(&data->update_lock); in intrusion0_alarm_store()
1111 static inline void nct6683_init_device(struct nct6683_data *data) in nct6683_init_device() argument
1116 tmp = nct6683_read(data, NCT6683_HWM_CFG); in nct6683_init_device()
1118 nct6683_write(data, NCT6683_HWM_CFG, tmp | 0x80); in nct6683_init_device()
1126 nct6683_setup_fans(struct nct6683_data *data) in nct6683_setup_fans() argument
1129 u8 reg; in nct6683_setup_fans() local
1132 reg = nct6683_read(data, NCT6683_REG_FANIN_CFG(i)); in nct6683_setup_fans()
1133 if (reg & 0x80) in nct6683_setup_fans()
1134 data->have_fan |= 1 << i; in nct6683_setup_fans()
1135 data->fanin_cfg[i] = reg; in nct6683_setup_fans()
1138 reg = nct6683_read(data, NCT6683_REG_FANOUT_CFG(i)); in nct6683_setup_fans()
1139 if (reg & 0x80) in nct6683_setup_fans()
1140 data->have_pwm |= 1 << i; in nct6683_setup_fans()
1141 data->fanout_cfg[i] = reg; in nct6683_setup_fans()
1161 static void nct6683_setup_sensors(struct nct6683_data *data) in nct6683_setup_sensors() argument
1163 u8 reg; in nct6683_setup_sensors() local
1166 data->temp_num = 0; in nct6683_setup_sensors()
1167 data->in_num = 0; in nct6683_setup_sensors()
1169 reg = nct6683_read(data, NCT6683_REG_MON_CFG(i)) & 0x7f; in nct6683_setup_sensors()
1171 if (reg >= NUM_MON_LABELS) in nct6683_setup_sensors()
1174 if (nct6683_mon_label[reg] == NULL) in nct6683_setup_sensors()
1176 if (reg < MON_VOLTAGE_START) { in nct6683_setup_sensors()
1177 data->temp_index[data->temp_num] = i; in nct6683_setup_sensors()
1178 data->temp_src[data->temp_num] = reg; in nct6683_setup_sensors()
1179 data->temp_num++; in nct6683_setup_sensors()
1181 data->in_index[data->in_num] = i; in nct6683_setup_sensors()
1182 data->in_src[data->in_num] = reg; in nct6683_setup_sensors()
1183 data->in_num++; in nct6683_setup_sensors()
1190 struct device *dev = &pdev->dev; in nct6683_probe()
1191 struct nct6683_sio_data *sio_data = dev->platform_data; in nct6683_probe()
1193 struct nct6683_data *data; in nct6683_probe() local
1200 if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME)) in nct6683_probe()
1201 return -EBUSY; in nct6683_probe()
1203 data = devm_kzalloc(dev, sizeof(struct nct6683_data), GFP_KERNEL); in nct6683_probe()
1204 if (!data) in nct6683_probe()
1205 return -ENOMEM; in nct6683_probe()
1207 data->kind = sio_data->kind; in nct6683_probe()
1208 data->sioreg = sio_data->sioreg; in nct6683_probe()
1209 data->addr = res->start; in nct6683_probe()
1210 mutex_init(&data->update_lock); in nct6683_probe()
1211 platform_set_drvdata(pdev, data); in nct6683_probe()
1213 data->customer_id = nct6683_read16(data, NCT6683_REG_CUSTOMER_ID); in nct6683_probe()
1216 switch (data->customer_id) { in nct6683_probe()
1223 return -ENODEV; in nct6683_probe()
1226 nct6683_init_device(data); in nct6683_probe()
1227 nct6683_setup_fans(data); in nct6683_probe()
1228 nct6683_setup_sensors(data); in nct6683_probe()
1232 if (data->have_pwm) { in nct6683_probe()
1235 fls(data->have_pwm)); in nct6683_probe()
1238 data->groups[groups++] = group; in nct6683_probe()
1241 if (data->in_num) { in nct6683_probe()
1244 data->in_num); in nct6683_probe()
1247 data->groups[groups++] = group; in nct6683_probe()
1250 if (data->have_fan) { in nct6683_probe()
1253 fls(data->have_fan)); in nct6683_probe()
1256 data->groups[groups++] = group; in nct6683_probe()
1259 if (data->temp_num) { in nct6683_probe()
1262 data->temp_num); in nct6683_probe()
1265 data->groups[groups++] = group; in nct6683_probe()
1267 data->groups[groups++] = &nct6683_group_other; in nct6683_probe()
1269 if (data->customer_id == NCT6683_CUSTOMER_ID_INTEL) in nct6683_probe()
1271 nct6683_read(data, NCT6683_REG_BUILD_MONTH), in nct6683_probe()
1272 nct6683_read(data, NCT6683_REG_BUILD_DAY), in nct6683_probe()
1273 nct6683_read(data, NCT6683_REG_BUILD_YEAR)); in nct6683_probe()
1276 nct6683_read(data, NCT6683_REG_BUILD_MONTH), in nct6683_probe()
1277 nct6683_read(data, NCT6683_REG_BUILD_DAY), in nct6683_probe()
1278 nct6683_read(data, NCT6683_REG_BUILD_YEAR)); in nct6683_probe()
1281 nct6683_chip_names[data->kind], in nct6683_probe()
1282 nct6683_read(data, NCT6683_REG_VERSION_HI), in nct6683_probe()
1283 nct6683_read(data, NCT6683_REG_VERSION_LO), in nct6683_probe()
1287 nct6683_device_names[data->kind], data, data->groups); in nct6683_probe()
1294 struct nct6683_data *data = nct6683_update_device(dev); in nct6683_suspend() local
1296 mutex_lock(&data->update_lock); in nct6683_suspend()
1297 data->hwm_cfg = nct6683_read(data, NCT6683_HWM_CFG); in nct6683_suspend()
1298 mutex_unlock(&data->update_lock); in nct6683_suspend()
1305 struct nct6683_data *data = dev_get_drvdata(dev); in nct6683_resume() local
1307 mutex_lock(&data->update_lock); in nct6683_resume()
1309 nct6683_write(data, NCT6683_HWM_CFG, data->hwm_cfg); in nct6683_resume()
1311 /* Force re-reading all values */ in nct6683_resume()
1312 data->valid = false; in nct6683_resume()
1313 mutex_unlock(&data->update_lock); in nct6683_resume()
1353 sio_data->kind = nct6683; in nct6683_find()
1374 pr_warn("Forcibly enabling EC access. Data may be unusable.\n"); in nct6683_find()
1380 nct6683_chip_names[sio_data->kind], sioaddr, addr); in nct6683_find()
1381 sio_data->sioreg = sioaddr; in nct6683_find()
1387 return -ENODEV; in nct6683_find()
1391 * when Super-I/O functions move to a separate file, the Super-I/O
1412 * initialize sio_data->kind and sio_data->sioreg. in sensors_nct6683_init()
1414 * when Super-I/O functions move to a separate file, the Super-I/O in sensors_nct6683_init()
1415 * driver will probe 0x2e and 0x4e and auto-detect the presence of a in sensors_nct6683_init()
1427 err = -ENOMEM; in sensors_nct6683_init()
1439 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; in sensors_nct6683_init()
1459 err = -ENODEV; in sensors_nct6683_init()
1468 while (--i >= 0) { in sensors_nct6683_init()
1488 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");