Lines Matching +full:data +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * nct7904.c - driver for Nuvoton NCT7904D.
92 #define FANCTL1_FMR_REG 0x00 /* Bank 3; 1 reg per channel */
93 #define FANCTL1_OUT_REG 0x10 /* Bank 3; 1 reg per channel */
110 /*The timeout range is 1-255 minutes*/
145 static int nct7904_bank_lock(struct nct7904_data *data, unsigned int bank) in nct7904_bank_lock() argument
149 mutex_lock(&data->bank_lock); in nct7904_bank_lock()
150 if (data->bank_sel == bank) in nct7904_bank_lock()
152 ret = i2c_smbus_write_byte_data(data->client, BANK_SEL_REG, bank); in nct7904_bank_lock()
154 data->bank_sel = bank; in nct7904_bank_lock()
156 data->bank_sel = -1; in nct7904_bank_lock()
160 static inline void nct7904_bank_release(struct nct7904_data *data) in nct7904_bank_release() argument
162 mutex_unlock(&data->bank_lock); in nct7904_bank_release()
165 /* Read 1-byte register. Returns unsigned reg or -ERRNO on error. */
166 static int nct7904_read_reg(struct nct7904_data *data, in nct7904_read_reg() argument
169 struct i2c_client *client = data->client; in nct7904_read_reg()
172 ret = nct7904_bank_lock(data, bank); in nct7904_read_reg()
176 nct7904_bank_release(data); in nct7904_read_reg()
181 * Read 2-byte register. Returns register in big-endian format or
182 * -ERRNO on error.
184 static int nct7904_read_reg16(struct nct7904_data *data, in nct7904_read_reg16() argument
187 struct i2c_client *client = data->client; in nct7904_read_reg16()
190 ret = nct7904_bank_lock(data, bank); in nct7904_read_reg16()
201 nct7904_bank_release(data); in nct7904_read_reg16()
205 /* Write 1-byte register. Returns 0 or -ERRNO on error. */
206 static int nct7904_write_reg(struct nct7904_data *data, in nct7904_write_reg() argument
209 struct i2c_client *client = data->client; in nct7904_write_reg()
212 ret = nct7904_bank_lock(data, bank); in nct7904_write_reg()
216 nct7904_bank_release(data); in nct7904_write_reg()
220 static int nct7904_read_fan(struct device *dev, u32 attr, int channel, in nct7904_read_fan() argument
223 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_read_fan() local
229 ret = nct7904_read_reg16(data, BANK_0, in nct7904_read_fan()
230 FANIN1_HV_REG + channel * 2); in nct7904_read_fan()
241 ret = nct7904_read_reg16(data, BANK_1, in nct7904_read_fan()
242 FANIN1_HV_HL_REG + channel * 2); in nct7904_read_fan()
253 ret = nct7904_read_reg(data, BANK_0, in nct7904_read_fan()
254 SMI_STS5_REG + (channel >> 3)); in nct7904_read_fan()
257 if (!data->fan_alarm[channel >> 3]) in nct7904_read_fan()
258 data->fan_alarm[channel >> 3] = ret & 0xff; in nct7904_read_fan()
261 data->fan_alarm[channel >> 3] |= (ret & 0xff); in nct7904_read_fan()
262 *val = (data->fan_alarm[channel >> 3] >> (channel & 0x07)) & 1; in nct7904_read_fan()
265 data->fan_alarm[channel >> 3] ^= 1 << (channel & 0x07); in nct7904_read_fan()
268 return -EOPNOTSUPP; in nct7904_read_fan()
272 static umode_t nct7904_fan_is_visible(const void *_data, u32 attr, int channel) in nct7904_fan_is_visible() argument
274 const struct nct7904_data *data = _data; in nct7904_fan_is_visible() local
279 if (data->fanin_mask & (1 << channel)) in nct7904_fan_is_visible()
283 if (data->fanin_mask & (1 << channel)) in nct7904_fan_is_visible()
299 static int nct7904_read_in(struct device *dev, u32 attr, int channel, in nct7904_read_in() argument
302 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_read_in() local
305 index = nct7904_chan_to_index[channel]; in nct7904_read_in()
309 ret = nct7904_read_reg16(data, BANK_0, in nct7904_read_in()
321 ret = nct7904_read_reg16(data, BANK_1, in nct7904_read_in()
333 ret = nct7904_read_reg16(data, BANK_1, in nct7904_read_in()
345 ret = nct7904_read_reg(data, BANK_0, in nct7904_read_in()
349 if (!data->vsen_alarm[index >> 3]) in nct7904_read_in()
350 data->vsen_alarm[index >> 3] = ret & 0xff; in nct7904_read_in()
353 data->vsen_alarm[index >> 3] |= (ret & 0xff); in nct7904_read_in()
354 *val = (data->vsen_alarm[index >> 3] >> (index & 0x07)) & 1; in nct7904_read_in()
357 data->vsen_alarm[index >> 3] ^= 1 << (index & 0x07); in nct7904_read_in()
360 return -EOPNOTSUPP; in nct7904_read_in()
364 static umode_t nct7904_in_is_visible(const void *_data, u32 attr, int channel) in nct7904_in_is_visible() argument
366 const struct nct7904_data *data = _data; in nct7904_in_is_visible() local
367 int index = nct7904_chan_to_index[channel]; in nct7904_in_is_visible()
372 if (channel > 0 && (data->vsen_mask & BIT(index))) in nct7904_in_is_visible()
377 if (channel > 0 && (data->vsen_mask & BIT(index))) in nct7904_in_is_visible()
387 static int nct7904_read_temp(struct device *dev, u32 attr, int channel, in nct7904_read_temp() argument
390 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_read_temp() local
397 if (channel == 4) in nct7904_read_temp()
398 ret = nct7904_read_reg16(data, BANK_0, LTD_HV_REG); in nct7904_read_temp()
399 else if (channel < 5) in nct7904_read_temp()
400 ret = nct7904_read_reg16(data, BANK_0, in nct7904_read_temp()
401 TEMP_CH1_HV_REG + channel * 4); in nct7904_read_temp()
403 ret = nct7904_read_reg16(data, BANK_0, in nct7904_read_temp()
404 T_CPU1_HV_REG + (channel - 5) in nct7904_read_temp()
412 if (channel == 4) { in nct7904_read_temp()
413 ret = nct7904_read_reg(data, BANK_0, in nct7904_read_temp()
418 } else if (channel < 4) { in nct7904_read_temp()
419 ret = nct7904_read_reg(data, BANK_0, in nct7904_read_temp()
423 *val = (ret >> (((channel * 2) + 1) & 0x07)) & 1; in nct7904_read_temp()
425 if ((channel - 5) < 4) { in nct7904_read_temp()
426 ret = nct7904_read_reg(data, BANK_0, in nct7904_read_temp()
428 ((channel - 5) >> 3)); in nct7904_read_temp()
431 *val = (ret >> ((channel - 5) & 0x07)) & 1; in nct7904_read_temp()
433 ret = nct7904_read_reg(data, BANK_0, in nct7904_read_temp()
435 ((channel - 5) >> 3)); in nct7904_read_temp()
438 *val = (ret >> (((channel - 5) & 0x07) - 4)) in nct7904_read_temp()
444 if (channel < 5) { in nct7904_read_temp()
445 if ((data->tcpu_mask >> channel) & 0x01) { in nct7904_read_temp()
446 if ((data->temp_mode >> channel) & 0x01) in nct7904_read_temp()
454 if ((data->has_dts >> (channel - 5)) & 0x01) { in nct7904_read_temp()
455 if (data->enable_dts & ENABLE_TSI) in nct7904_read_temp()
485 return -EOPNOTSUPP; in nct7904_read_temp()
488 if (channel == 4) in nct7904_read_temp()
489 ret = nct7904_read_reg(data, BANK_1, reg1); in nct7904_read_temp()
490 else if (channel < 5) in nct7904_read_temp()
491 ret = nct7904_read_reg(data, BANK_1, in nct7904_read_temp()
492 reg2 + channel * 8); in nct7904_read_temp()
494 ret = nct7904_read_reg(data, BANK_1, in nct7904_read_temp()
495 reg3 + (channel - 5) * 4); in nct7904_read_temp()
504 static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel) in nct7904_temp_is_visible() argument
506 const struct nct7904_data *data = _data; in nct7904_temp_is_visible() local
512 if (channel < 5) { in nct7904_temp_is_visible()
513 if (data->tcpu_mask & BIT(channel)) in nct7904_temp_is_visible()
516 if (data->has_dts & BIT(channel - 5)) in nct7904_temp_is_visible()
524 if (channel < 5) { in nct7904_temp_is_visible()
525 if (data->tcpu_mask & BIT(channel)) in nct7904_temp_is_visible()
528 if (data->has_dts & BIT(channel - 5)) in nct7904_temp_is_visible()
539 static int nct7904_read_pwm(struct device *dev, u32 attr, int channel, in nct7904_read_pwm() argument
542 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_read_pwm() local
547 ret = nct7904_read_reg(data, BANK_3, FANCTL1_OUT_REG + channel); in nct7904_read_pwm()
553 ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + channel); in nct7904_read_pwm()
560 return -EOPNOTSUPP; in nct7904_read_pwm()
564 static int nct7904_write_temp(struct device *dev, u32 attr, int channel, in nct7904_write_temp() argument
567 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_write_temp() local
571 val = clamp_val(val / 1000, -128, 127); in nct7904_write_temp()
595 return -EOPNOTSUPP; in nct7904_write_temp()
597 if (channel == 4) in nct7904_write_temp()
598 ret = nct7904_write_reg(data, BANK_1, reg1, val); in nct7904_write_temp()
599 else if (channel < 5) in nct7904_write_temp()
600 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_temp()
601 reg2 + channel * 8, val); in nct7904_write_temp()
603 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_temp()
604 reg3 + (channel - 5) * 4, val); in nct7904_write_temp()
609 static int nct7904_write_fan(struct device *dev, u32 attr, int channel, in nct7904_write_fan() argument
612 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_write_fan() local
619 return -EINVAL; in nct7904_write_fan()
623 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_fan()
624 FANIN1_HV_HL_REG + channel * 2, tmp); in nct7904_write_fan()
628 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_fan()
629 FANIN1_LV_HL_REG + channel * 2, tmp); in nct7904_write_fan()
632 return -EOPNOTSUPP; in nct7904_write_fan()
636 static int nct7904_write_in(struct device *dev, u32 attr, int channel, in nct7904_write_in() argument
639 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_write_in() local
642 index = nct7904_chan_to_index[channel]; in nct7904_write_in()
653 tmp = nct7904_read_reg(data, BANK_1, in nct7904_write_in()
659 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_in()
663 tmp = nct7904_read_reg(data, BANK_1, in nct7904_write_in()
668 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_in()
672 tmp = nct7904_read_reg(data, BANK_1, in nct7904_write_in()
678 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_in()
682 tmp = nct7904_read_reg(data, BANK_1, in nct7904_write_in()
687 ret = nct7904_write_reg(data, BANK_1, in nct7904_write_in()
691 return -EOPNOTSUPP; in nct7904_write_in()
695 static int nct7904_write_pwm(struct device *dev, u32 attr, int channel, in nct7904_write_pwm() argument
698 struct nct7904_data *data = dev_get_drvdata(dev); in nct7904_write_pwm() local
704 return -EINVAL; in nct7904_write_pwm()
705 ret = nct7904_write_reg(data, BANK_3, FANCTL1_OUT_REG + channel, in nct7904_write_pwm()
710 (val == 2 && !data->fan_mode[channel])) in nct7904_write_pwm()
711 return -EINVAL; in nct7904_write_pwm()
712 ret = nct7904_write_reg(data, BANK_3, FANCTL1_FMR_REG + channel, in nct7904_write_pwm()
713 val == 2 ? data->fan_mode[channel] : 0); in nct7904_write_pwm()
716 return -EOPNOTSUPP; in nct7904_write_pwm()
720 static umode_t nct7904_pwm_is_visible(const void *_data, u32 attr, int channel) in nct7904_pwm_is_visible() argument
732 u32 attr, int channel, long *val) in nct7904_read() argument
736 return nct7904_read_in(dev, attr, channel, val); in nct7904_read()
738 return nct7904_read_fan(dev, attr, channel, val); in nct7904_read()
740 return nct7904_read_pwm(dev, attr, channel, val); in nct7904_read()
742 return nct7904_read_temp(dev, attr, channel, val); in nct7904_read()
744 return -EOPNOTSUPP; in nct7904_read()
749 u32 attr, int channel, long val) in nct7904_write() argument
753 return nct7904_write_in(dev, attr, channel, val); in nct7904_write()
755 return nct7904_write_fan(dev, attr, channel, val); in nct7904_write()
757 return nct7904_write_pwm(dev, attr, channel, val); in nct7904_write()
759 return nct7904_write_temp(dev, attr, channel, val); in nct7904_write()
761 return -EOPNOTSUPP; in nct7904_write()
765 static umode_t nct7904_is_visible(const void *data, in nct7904_is_visible() argument
767 u32 attr, int channel) in nct7904_is_visible() argument
771 return nct7904_in_is_visible(data, attr, channel); in nct7904_is_visible()
773 return nct7904_fan_is_visible(data, attr, channel); in nct7904_is_visible()
775 return nct7904_pwm_is_visible(data, attr, channel); in nct7904_is_visible()
777 return nct7904_temp_is_visible(data, attr, channel); in nct7904_is_visible()
783 /* Return 0 if detection is successful, -ENODEV otherwise */
787 struct i2c_adapter *adapter = client->adapter; in nct7904_detect()
792 return -ENODEV; in nct7904_detect()
799 return -ENODEV; in nct7904_detect()
801 strscpy(info->type, "nct7904", I2C_NAME_SIZE); in nct7904_detect()
928 struct nct7904_data *data = watchdog_get_drvdata(wdt); in nct7904_wdt_start() local
931 return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_EN); in nct7904_wdt_start()
936 struct nct7904_data *data = watchdog_get_drvdata(wdt); in nct7904_wdt_stop() local
938 return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_DIS); in nct7904_wdt_stop()
944 struct nct7904_data *data = watchdog_get_drvdata(wdt); in nct7904_wdt_set_timeout() local
947 * Its minimum unit is minutes. And wdt->timeout needs in nct7904_wdt_set_timeout()
949 * to be: wdt->timeout = timeout / 60 * 60. in nct7904_wdt_set_timeout()
952 * So, wdt->timeout must then be set to 60 seconds. in nct7904_wdt_set_timeout()
954 wdt->timeout = timeout / 60 * 60; in nct7904_wdt_set_timeout()
956 return nct7904_write_reg(data, BANK_0, WDT_TIMER_REG, in nct7904_wdt_set_timeout()
957 wdt->timeout / 60); in nct7904_wdt_set_timeout()
968 struct nct7904_data *data = watchdog_get_drvdata(wdt); in nct7904_wdt_ping() local
972 ret = nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_DIS); in nct7904_wdt_ping()
977 ret = nct7904_write_reg(data, BANK_0, WDT_TIMER_REG, wdt->timeout / 60); in nct7904_wdt_ping()
982 return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_EN); in nct7904_wdt_ping()
987 struct nct7904_data *data = watchdog_get_drvdata(wdt); in nct7904_wdt_get_timeleft() local
990 ret = nct7904_read_reg(data, BANK_0, WDT_TIMER_REG); in nct7904_wdt_get_timeleft()
1014 struct nct7904_data *data; in nct7904_probe() local
1016 struct device *dev = &client->dev; in nct7904_probe()
1021 data = devm_kzalloc(dev, sizeof(struct nct7904_data), GFP_KERNEL); in nct7904_probe()
1022 if (!data) in nct7904_probe()
1023 return -ENOMEM; in nct7904_probe()
1025 data->client = client; in nct7904_probe()
1026 mutex_init(&data->bank_lock); in nct7904_probe()
1027 data->bank_sel = -1; in nct7904_probe()
1031 ret = nct7904_read_reg16(data, BANK_0, FANIN_CTRL0_REG); in nct7904_probe()
1034 data->fanin_mask = (ret >> 8) | ((ret & 0xff) << 8); in nct7904_probe()
1044 ret = nct7904_read_reg16(data, BANK_0, VT_ADC_CTRL0_REG); in nct7904_probe()
1047 ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG); in nct7904_probe()
1050 data->vsen_mask = mask; in nct7904_probe()
1053 ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL0_REG); in nct7904_probe()
1058 data->tcpu_mask |= 1; /* TR1 */ in nct7904_probe()
1060 data->tcpu_mask |= 2; /* TR2 */ in nct7904_probe()
1062 data->tcpu_mask |= 4; /* TR3 */ in nct7904_probe()
1064 data->tcpu_mask |= 8; /* TR4 */ in nct7904_probe()
1067 ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG); in nct7904_probe()
1071 data->tcpu_mask |= 0x10; in nct7904_probe()
1073 /* Multi-Function detecting for Volt and TR/TD */ in nct7904_probe()
1074 ret = nct7904_read_reg(data, BANK_0, VT_ADC_MD_REG); in nct7904_probe()
1078 data->temp_mode = 0; in nct7904_probe()
1083 data->tcpu_mask &= ~bit; in nct7904_probe()
1085 data->temp_mode |= bit; in nct7904_probe()
1086 data->vsen_mask &= ~(0x06 << (i * 2)); in nct7904_probe()
1088 data->vsen_mask &= ~(0x02 << (i * 2)); in nct7904_probe()
1091 data->tcpu_mask &= ~bit; in nct7904_probe()
1092 data->vsen_mask &= ~(0x06 << (i * 2)); in nct7904_probe()
1097 ret = nct7904_read_reg(data, BANK_2, PFE_REG); in nct7904_probe()
1101 data->enable_dts = 1; /* Enable DTS & PECI */ in nct7904_probe()
1103 ret = nct7904_read_reg(data, BANK_2, TSI_CTRL_REG); in nct7904_probe()
1107 data->enable_dts = 0x3; /* Enable DTS & TSI */ in nct7904_probe()
1111 if (data->enable_dts) { in nct7904_probe()
1112 ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL0_REG); in nct7904_probe()
1115 data->has_dts = ret & 0xF; in nct7904_probe()
1116 if (data->enable_dts & ENABLE_TSI) { in nct7904_probe()
1117 ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL1_REG); in nct7904_probe()
1120 data->has_dts |= (ret & 0xF) << 4; in nct7904_probe()
1125 ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + i); in nct7904_probe()
1128 data->fan_mode[i] = ret; in nct7904_probe()
1133 ret = nct7904_read_reg(data, BANK_0, SMI_STS1_REG + i); in nct7904_probe()
1139 devm_hwmon_device_register_with_info(dev, client->name, data, in nct7904_probe()
1146 data->wdt.ops = &nct7904_wdt_ops; in nct7904_probe()
1147 data->wdt.info = &nct7904_wdt_info; in nct7904_probe()
1149 data->wdt.timeout = WATCHDOG_TIMEOUT * 60; /* Set default timeout */ in nct7904_probe()
1150 data->wdt.min_timeout = MIN_TIMEOUT; in nct7904_probe()
1151 data->wdt.max_timeout = MAX_TIMEOUT; in nct7904_probe()
1152 data->wdt.parent = &client->dev; in nct7904_probe()
1154 watchdog_init_timeout(&data->wdt, timeout * 60, &client->dev); in nct7904_probe()
1155 watchdog_set_nowayout(&data->wdt, nowayout); in nct7904_probe()
1156 watchdog_set_drvdata(&data->wdt, data); in nct7904_probe()
1158 watchdog_stop_on_unregister(&data->wdt); in nct7904_probe()
1160 return devm_watchdog_register_device(dev, &data->wdt); in nct7904_probe()