^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * nct7904.c - driver for Nuvoton NCT7904D.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2015 Kontron
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2019 Advantech
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Author: Amy.Shih <amy.shih@advantech.com.tw>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (c) 2020 Advantech
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Author: Yuechao Zhao <yuechao.zhao@advantech.com.cn>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Supports the following chips:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Chip #vin #fan #pwm #temp #dts chip ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * nct7904d 20 12 4 5 8 0xc5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/watchdog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define VENDOR_ID_REG 0x7A /* Any bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define NUVOTON_ID 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CHIP_ID_REG 0x7B /* Any bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define NCT7904_ID 0xC5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DEVICE_ID_REG 0x7C /* Any bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define BANK_SEL_REG 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BANK_0 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BANK_1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define BANK_2 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define BANK_3 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define BANK_4 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define BANK_MAX 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define FANIN_MAX 12 /* Counted from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define VSEN_MAX 21 /* VSEN1..14, 3VDD, VBAT, V3VSB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) LTD (not a voltage), VSEN17..19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define FANCTL_MAX 4 /* Counted from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TCPU_MAX 8 /* Counted from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TEMP_MAX 4 /* Counted from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SMI_STS_MAX 10 /* Counted from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define VT_ADC_CTRL0_REG 0x20 /* Bank 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define VT_ADC_CTRL1_REG 0x21 /* Bank 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define VT_ADC_CTRL2_REG 0x22 /* Bank 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define FANIN_CTRL0_REG 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define FANIN_CTRL1_REG 0x25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define DTS_T_CTRL0_REG 0x26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define DTS_T_CTRL1_REG 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define VT_ADC_MD_REG 0x2E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define VSEN1_HV_LL_REG 0x02 /* Bank 1; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define VSEN1_LV_LL_REG 0x03 /* Bank 1; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define VSEN1_HV_HL_REG 0x00 /* Bank 1; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define VSEN1_LV_HL_REG 0x01 /* Bank 1; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define SMI_STS1_REG 0xC1 /* Bank 0; SMI Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define SMI_STS3_REG 0xC3 /* Bank 0; SMI Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SMI_STS5_REG 0xC5 /* Bank 0; SMI Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define SMI_STS7_REG 0xC7 /* Bank 0; SMI Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define SMI_STS8_REG 0xC8 /* Bank 0; SMI Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define VSEN1_HV_REG 0x40 /* Bank 0; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define TEMP_CH1_HV_REG 0x42 /* Bank 0; same as VSEN2_HV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define LTD_HV_REG 0x62 /* Bank 0; 2 regs in VSEN range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define LTD_HV_HL_REG 0x44 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define LTD_LV_HL_REG 0x45 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define LTD_HV_LL_REG 0x46 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define LTD_LV_LL_REG 0x47 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define TEMP_CH1_CH_REG 0x05 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define TEMP_CH1_W_REG 0x06 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define TEMP_CH1_WH_REG 0x07 /* Bank 1; 1 reg for LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define TEMP_CH1_C_REG 0x04 /* Bank 1; 1 reg per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define DTS_T_CPU1_C_REG 0x90 /* Bank 1; 1 reg per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define DTS_T_CPU1_CH_REG 0x91 /* Bank 1; 1 reg per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define DTS_T_CPU1_W_REG 0x92 /* Bank 1; 1 reg per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define DTS_T_CPU1_WH_REG 0x93 /* Bank 1; 1 reg per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define FANIN1_HV_REG 0x80 /* Bank 0; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define FANIN1_HV_HL_REG 0x60 /* Bank 1; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define FANIN1_LV_HL_REG 0x61 /* Bank 1; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define T_CPU1_HV_REG 0xA0 /* Bank 0; 2 regs (HV/LV) per sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define PRTS_REG 0x03 /* Bank 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define PFE_REG 0x00 /* Bank 2; PECI Function Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define TSI_CTRL_REG 0x50 /* Bank 2; TSI Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define FANCTL1_FMR_REG 0x00 /* Bank 3; 1 reg per channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define FANCTL1_OUT_REG 0x10 /* Bank 3; 1 reg per channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define WDT_LOCK_REG 0xE0 /* W/O Lock Watchdog Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define WDT_EN_REG 0xE1 /* R/O Watchdog Enable Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define WDT_STS_REG 0xE2 /* R/O Watchdog Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define WDT_TIMER_REG 0xE3 /* R/W Watchdog Timer Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define WDT_SOFT_EN 0x55 /* Enable soft watchdog timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define WDT_SOFT_DIS 0xAA /* Disable soft watchdog timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define VOLT_MONITOR_MODE 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define THERMAL_DIODE_MODE 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define THERMISTOR_MODE 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define ENABLE_TSI BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define WATCHDOG_TIMEOUT 1 /* 1 minute default timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /*The timeout range is 1-255 minutes*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define MIN_TIMEOUT (1 * 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MAX_TIMEOUT (255 * 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) module_param(timeout, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes. 1 <= timeout <= 255, default="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static bool nowayout = WATCHDOG_NOWAYOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) module_param(nowayout, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static const unsigned short normal_i2c[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 0x2d, 0x2e, I2C_CLIENT_END
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct nct7904_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct watchdog_device wdt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct mutex bank_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int bank_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u32 fanin_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 vsen_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u32 tcpu_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u8 fan_mode[FANCTL_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u8 enable_dts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 has_dts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u8 temp_mode; /* 0: TR mode, 1: TD mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u8 fan_alarm[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u8 vsen_alarm[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Access functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int nct7904_bank_lock(struct nct7904_data *data, unsigned int bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) mutex_lock(&data->bank_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (data->bank_sel == bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ret = i2c_smbus_write_byte_data(data->client, BANK_SEL_REG, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) data->bank_sel = bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) data->bank_sel = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static inline void nct7904_bank_release(struct nct7904_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) mutex_unlock(&data->bank_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Read 1-byte register. Returns unsigned reg or -ERRNO on error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int nct7904_read_reg(struct nct7904_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int bank, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct i2c_client *client = data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = nct7904_bank_lock(data, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ret = i2c_smbus_read_byte_data(client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) nct7904_bank_release(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Read 2-byte register. Returns register in big-endian format or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * -ERRNO on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int nct7904_read_reg16(struct nct7904_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int bank, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct i2c_client *client = data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int ret, hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = nct7904_bank_lock(data, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ret = i2c_smbus_read_byte_data(client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) hi = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ret = i2c_smbus_read_byte_data(client, reg + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ret |= hi << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) nct7904_bank_release(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Write 1-byte register. Returns 0 or -ERRNO on error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int nct7904_write_reg(struct nct7904_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) unsigned int bank, unsigned int reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct i2c_client *client = data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = nct7904_bank_lock(data, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = i2c_smbus_write_byte_data(client, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) nct7904_bank_release(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int nct7904_read_fan(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) unsigned int cnt, rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) case hwmon_fan_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = nct7904_read_reg16(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) FANIN1_HV_REG + channel * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (cnt == 0 || cnt == 0x1fff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) rpm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) rpm = 1350000 / cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *val = rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case hwmon_fan_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ret = nct7904_read_reg16(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) FANIN1_HV_HL_REG + channel * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (cnt == 0 || cnt == 0x1fff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rpm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) rpm = 1350000 / cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *val = rpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) case hwmon_fan_alarm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ret = nct7904_read_reg(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) SMI_STS5_REG + (channel >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!data->fan_alarm[channel >> 3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) data->fan_alarm[channel >> 3] = ret & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* If there is new alarm showing up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) data->fan_alarm[channel >> 3] |= (ret & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) *val = (data->fan_alarm[channel >> 3] >> (channel & 0x07)) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Needs to clean the alarm if alarm existing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (*val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) data->fan_alarm[channel >> 3] ^= 1 << (channel & 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static umode_t nct7904_fan_is_visible(const void *_data, u32 attr, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) const struct nct7904_data *data = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case hwmon_fan_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) case hwmon_fan_alarm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (data->fanin_mask & (1 << channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) case hwmon_fan_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (data->fanin_mask & (1 << channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0644;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static u8 nct7904_chan_to_index[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 0, /* Not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 18, 19, 20, 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int nct7904_read_in(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int ret, volt, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) index = nct7904_chan_to_index[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case hwmon_in_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ret = nct7904_read_reg16(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) VSEN1_HV_REG + index * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (index < 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) volt *= 2; /* 0.002V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) volt *= 6; /* 0.006V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) *val = volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case hwmon_in_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = nct7904_read_reg16(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) VSEN1_HV_LL_REG + index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (index < 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) volt *= 2; /* 0.002V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) volt *= 6; /* 0.006V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *val = volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case hwmon_in_max:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = nct7904_read_reg16(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) VSEN1_HV_HL_REG + index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) volt = ((ret & 0xff00) >> 5) | (ret & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (index < 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) volt *= 2; /* 0.002V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) volt *= 6; /* 0.006V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *val = volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case hwmon_in_alarm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ret = nct7904_read_reg(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) SMI_STS1_REG + (index >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!data->vsen_alarm[index >> 3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) data->vsen_alarm[index >> 3] = ret & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* If there is new alarm showing up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) data->vsen_alarm[index >> 3] |= (ret & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *val = (data->vsen_alarm[index >> 3] >> (index & 0x07)) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* Needs to clean the alarm if alarm existing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (*val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) data->vsen_alarm[index >> 3] ^= 1 << (index & 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static umode_t nct7904_in_is_visible(const void *_data, u32 attr, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) const struct nct7904_data *data = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int index = nct7904_chan_to_index[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case hwmon_in_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case hwmon_in_alarm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (channel > 0 && (data->vsen_mask & BIT(index)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case hwmon_in_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case hwmon_in_max:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (channel > 0 && (data->vsen_mask & BIT(index)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return 0644;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static int nct7904_read_temp(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int ret, temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unsigned int reg1, reg2, reg3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) s8 temps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case hwmon_temp_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (channel == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = nct7904_read_reg16(data, BANK_0, LTD_HV_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) else if (channel < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ret = nct7904_read_reg16(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) TEMP_CH1_HV_REG + channel * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ret = nct7904_read_reg16(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) T_CPU1_HV_REG + (channel - 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) temp = ((ret & 0xff00) >> 5) | (ret & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) *val = sign_extend32(temp, 10) * 125;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) case hwmon_temp_alarm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (channel == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) ret = nct7904_read_reg(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) SMI_STS3_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *val = (ret >> 1) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else if (channel < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = nct7904_read_reg(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) SMI_STS1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) *val = (ret >> (((channel * 2) + 1) & 0x07)) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if ((channel - 5) < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) ret = nct7904_read_reg(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) SMI_STS7_REG +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ((channel - 5) >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) *val = (ret >> ((channel - 5) & 0x07)) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ret = nct7904_read_reg(data, BANK_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) SMI_STS8_REG +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ((channel - 5) >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *val = (ret >> (((channel - 5) & 0x07) - 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case hwmon_temp_type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (channel < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if ((data->tcpu_mask >> channel) & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if ((data->temp_mode >> channel) & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *val = 3; /* TD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) *val = 4; /* TR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if ((data->has_dts >> (channel - 5)) & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (data->enable_dts & ENABLE_TSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) *val = 5; /* TSI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) *val = 6; /* PECI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) case hwmon_temp_max:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) reg1 = LTD_HV_LL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) reg2 = TEMP_CH1_W_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) reg3 = DTS_T_CPU1_W_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case hwmon_temp_max_hyst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) reg1 = LTD_LV_LL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) reg2 = TEMP_CH1_WH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) reg3 = DTS_T_CPU1_WH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) case hwmon_temp_crit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) reg1 = LTD_HV_HL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) reg2 = TEMP_CH1_C_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) reg3 = DTS_T_CPU1_C_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case hwmon_temp_crit_hyst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) reg1 = LTD_LV_HL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) reg2 = TEMP_CH1_CH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) reg3 = DTS_T_CPU1_CH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (channel == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ret = nct7904_read_reg(data, BANK_1, reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) else if (channel < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ret = nct7904_read_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) reg2 + channel * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ret = nct7904_read_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) reg3 + (channel - 5) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) temps = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) *val = temps * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static umode_t nct7904_temp_is_visible(const void *_data, u32 attr, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) const struct nct7904_data *data = _data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) case hwmon_temp_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case hwmon_temp_alarm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case hwmon_temp_type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (channel < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (data->tcpu_mask & BIT(channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (data->has_dts & BIT(channel - 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case hwmon_temp_max:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) case hwmon_temp_max_hyst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case hwmon_temp_crit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case hwmon_temp_crit_hyst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (channel < 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (data->tcpu_mask & BIT(channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return 0644;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (data->has_dts & BIT(channel - 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return 0644;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int nct7904_read_pwm(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) case hwmon_pwm_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) ret = nct7904_read_reg(data, BANK_3, FANCTL1_OUT_REG + channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case hwmon_pwm_enable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) *val = ret ? 2 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static int nct7904_write_temp(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) unsigned int reg1, reg2, reg3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) val = clamp_val(val / 1000, -128, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case hwmon_temp_max:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) reg1 = LTD_HV_LL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) reg2 = TEMP_CH1_W_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) reg3 = DTS_T_CPU1_W_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case hwmon_temp_max_hyst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) reg1 = LTD_LV_LL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) reg2 = TEMP_CH1_WH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) reg3 = DTS_T_CPU1_WH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) case hwmon_temp_crit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) reg1 = LTD_HV_HL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) reg2 = TEMP_CH1_C_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) reg3 = DTS_T_CPU1_C_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) case hwmon_temp_crit_hyst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) reg1 = LTD_LV_HL_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) reg2 = TEMP_CH1_CH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) reg3 = DTS_T_CPU1_CH_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (channel == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ret = nct7904_write_reg(data, BANK_1, reg1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) else if (channel < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) reg2 + channel * 8, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) reg3 + (channel - 5) * 4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int nct7904_write_fan(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) case hwmon_fan_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (val <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) val = clamp_val(DIV_ROUND_CLOSEST(1350000, val), 1, 0x1fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) tmp = (val >> 5) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) FANIN1_HV_HL_REG + channel * 2, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) tmp = val & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) FANIN1_LV_HL_REG + channel * 2, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int nct7904_write_in(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) int ret, index, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) index = nct7904_chan_to_index[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (index < 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) val = val / 2; /* 0.002V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) val = val / 6; /* 0.006V scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) val = clamp_val(val, 0, 0x7ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) case hwmon_in_min:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) tmp = nct7904_read_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) VSEN1_LV_LL_REG + index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (tmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) tmp &= ~0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) tmp |= val & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) VSEN1_LV_LL_REG + index * 4, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) tmp = nct7904_read_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) VSEN1_HV_LL_REG + index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (tmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) tmp = (val >> 3) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) VSEN1_HV_LL_REG + index * 4, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) case hwmon_in_max:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) tmp = nct7904_read_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) VSEN1_LV_HL_REG + index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (tmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) tmp &= ~0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) tmp |= val & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) VSEN1_LV_HL_REG + index * 4, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) tmp = nct7904_read_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) VSEN1_HV_HL_REG + index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (tmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) tmp = (val >> 3) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ret = nct7904_write_reg(data, BANK_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) VSEN1_HV_HL_REG + index * 4, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int nct7904_write_pwm(struct device *dev, u32 attr, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct nct7904_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case hwmon_pwm_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (val < 0 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ret = nct7904_write_reg(data, BANK_3, FANCTL1_OUT_REG + channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case hwmon_pwm_enable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (val < 1 || val > 2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) (val == 2 && !data->fan_mode[channel]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ret = nct7904_write_reg(data, BANK_3, FANCTL1_FMR_REG + channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) val == 2 ? data->fan_mode[channel] : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static umode_t nct7904_pwm_is_visible(const void *_data, u32 attr, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) switch (attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case hwmon_pwm_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case hwmon_pwm_enable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0644;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static int nct7904_read(struct device *dev, enum hwmon_sensor_types type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u32 attr, int channel, long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) case hwmon_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return nct7904_read_in(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) case hwmon_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return nct7904_read_fan(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case hwmon_pwm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return nct7904_read_pwm(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case hwmon_temp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return nct7904_read_temp(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static int nct7904_write(struct device *dev, enum hwmon_sensor_types type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) u32 attr, int channel, long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) case hwmon_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return nct7904_write_in(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case hwmon_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return nct7904_write_fan(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) case hwmon_pwm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return nct7904_write_pwm(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) case hwmon_temp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return nct7904_write_temp(dev, attr, channel, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static umode_t nct7904_is_visible(const void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) enum hwmon_sensor_types type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) u32 attr, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case hwmon_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return nct7904_in_is_visible(data, attr, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case hwmon_fan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return nct7904_fan_is_visible(data, attr, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case hwmon_pwm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return nct7904_pwm_is_visible(data, attr, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case hwmon_temp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return nct7904_temp_is_visible(data, attr, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* Return 0 if detection is successful, -ENODEV otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int nct7904_detect(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct i2c_board_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct i2c_adapter *adapter = client->adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (!i2c_check_functionality(adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) I2C_FUNC_SMBUS_READ_BYTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* Determine the chip type. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (i2c_smbus_read_byte_data(client, VENDOR_ID_REG) != NUVOTON_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) i2c_smbus_read_byte_data(client, CHIP_ID_REG) != NCT7904_ID ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) (i2c_smbus_read_byte_data(client, DEVICE_ID_REG) & 0xf0) != 0x50 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) (i2c_smbus_read_byte_data(client, BANK_SEL_REG) & 0xf8) != 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) strlcpy(info->type, "nct7904", I2C_NAME_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static const struct hwmon_channel_info *nct7904_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) HWMON_CHANNEL_INFO(in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /* dummy, skipped in is_visible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) HWMON_I_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) HWMON_I_ALARM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) HWMON_CHANNEL_INFO(fan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) HWMON_CHANNEL_INFO(pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) HWMON_CHANNEL_INFO(temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) HWMON_T_CRIT_HYST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) HWMON_T_CRIT_HYST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static const struct hwmon_ops nct7904_hwmon_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .is_visible = nct7904_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .read = nct7904_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .write = nct7904_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) static const struct hwmon_chip_info nct7904_chip_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .ops = &nct7904_hwmon_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .info = nct7904_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * Watchdog Function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) static int nct7904_wdt_start(struct watchdog_device *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct nct7904_data *data = watchdog_get_drvdata(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /* Enable soft watchdog timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static int nct7904_wdt_stop(struct watchdog_device *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) struct nct7904_data *data = watchdog_get_drvdata(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int nct7904_wdt_set_timeout(struct watchdog_device *wdt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) unsigned int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct nct7904_data *data = watchdog_get_drvdata(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * The NCT7904 is very special in watchdog function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * Its minimum unit is minutes. And wdt->timeout needs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * to match the actual timeout selected. So, this needs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * to be: wdt->timeout = timeout / 60 * 60.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * For example, if the user configures a timeout of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * 119 seconds, the actual timeout will be 60 seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * So, wdt->timeout must then be set to 60 seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) wdt->timeout = timeout / 60 * 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return nct7904_write_reg(data, BANK_0, WDT_TIMER_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) wdt->timeout / 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static int nct7904_wdt_ping(struct watchdog_device *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * NCT7904 does not support refreshing WDT_TIMER_REG register when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * the watchdog is active. Please disable watchdog before feeding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * the watchdog and enable it again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct nct7904_data *data = watchdog_get_drvdata(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /* Disable soft watchdog timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) ret = nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) /* feed watchdog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) ret = nct7904_write_reg(data, BANK_0, WDT_TIMER_REG, wdt->timeout / 60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* Enable soft watchdog timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return nct7904_write_reg(data, BANK_0, WDT_LOCK_REG, WDT_SOFT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static unsigned int nct7904_wdt_get_timeleft(struct watchdog_device *wdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) struct nct7904_data *data = watchdog_get_drvdata(wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) ret = nct7904_read_reg(data, BANK_0, WDT_TIMER_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return ret * 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static const struct watchdog_info nct7904_wdt_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) WDIOF_MAGICCLOSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) .identity = "nct7904 watchdog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) static const struct watchdog_ops nct7904_wdt_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) .start = nct7904_wdt_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) .stop = nct7904_wdt_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) .ping = nct7904_wdt_ping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) .set_timeout = nct7904_wdt_set_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) .get_timeleft = nct7904_wdt_get_timeleft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static int nct7904_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct nct7904_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) u8 val, bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) data = devm_kzalloc(dev, sizeof(struct nct7904_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) mutex_init(&data->bank_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) data->bank_sel = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* Setup sensor groups. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* FANIN attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ret = nct7904_read_reg16(data, BANK_0, FANIN_CTRL0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) data->fanin_mask = (ret >> 8) | ((ret & 0xff) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * VSEN attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * Note: voltage sensors overlap with external temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * sensors. So, if we ever decide to support the latter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * we will have to adjust 'vsen_mask' accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ret = nct7904_read_reg16(data, BANK_0, VT_ADC_CTRL0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) mask = (ret >> 8) | ((ret & 0xff) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) mask |= (ret << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) data->vsen_mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /* CPU_TEMP attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if ((ret & 0x6) == 0x6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) data->tcpu_mask |= 1; /* TR1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if ((ret & 0x18) == 0x18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) data->tcpu_mask |= 2; /* TR2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if ((ret & 0x20) == 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) data->tcpu_mask |= 4; /* TR3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if ((ret & 0x80) == 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) data->tcpu_mask |= 8; /* TR4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /* LTD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ret = nct7904_read_reg(data, BANK_0, VT_ADC_CTRL2_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if ((ret & 0x02) == 0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) data->tcpu_mask |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /* Multi-Function detecting for Volt and TR/TD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) ret = nct7904_read_reg(data, BANK_0, VT_ADC_MD_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) data->temp_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) val = (ret >> (i * 2)) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) bit = (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (val == VOLT_MONITOR_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) data->tcpu_mask &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) } else if (val == THERMAL_DIODE_MODE && i < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) data->temp_mode |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) data->vsen_mask &= ~(0x06 << (i * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) } else if (val == THERMISTOR_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) data->vsen_mask &= ~(0x02 << (i * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* Reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) data->tcpu_mask &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) data->vsen_mask &= ~(0x06 << (i * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) /* PECI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) ret = nct7904_read_reg(data, BANK_2, PFE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (ret & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) data->enable_dts = 1; /* Enable DTS & PECI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) ret = nct7904_read_reg(data, BANK_2, TSI_CTRL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (ret & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) data->enable_dts = 0x3; /* Enable DTS & TSI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) /* Check DTS enable status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (data->enable_dts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL0_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) data->has_dts = ret & 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (data->enable_dts & ENABLE_TSI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) ret = nct7904_read_reg(data, BANK_0, DTS_T_CTRL1_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) data->has_dts |= (ret & 0xF) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) for (i = 0; i < FANCTL_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) ret = nct7904_read_reg(data, BANK_3, FANCTL1_FMR_REG + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) data->fan_mode[i] = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) /* Read all of SMI status register to clear alarms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) for (i = 0; i < SMI_STS_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ret = nct7904_read_reg(data, BANK_0, SMI_STS1_REG + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) hwmon_dev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) devm_hwmon_device_register_with_info(dev, client->name, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) &nct7904_chip_info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ret = PTR_ERR_OR_ZERO(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* Watchdog initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) data->wdt.ops = &nct7904_wdt_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) data->wdt.info = &nct7904_wdt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) data->wdt.timeout = WATCHDOG_TIMEOUT * 60; /* Set default timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) data->wdt.min_timeout = MIN_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) data->wdt.max_timeout = MAX_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) data->wdt.parent = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) watchdog_init_timeout(&data->wdt, timeout * 60, &client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) watchdog_set_nowayout(&data->wdt, nowayout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) watchdog_set_drvdata(&data->wdt, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) watchdog_stop_on_unregister(&data->wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return devm_watchdog_register_device(dev, &data->wdt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static const struct i2c_device_id nct7904_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {"nct7904", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) MODULE_DEVICE_TABLE(i2c, nct7904_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static struct i2c_driver nct7904_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .class = I2C_CLASS_HWMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .name = "nct7904",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) .probe_new = nct7904_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) .id_table = nct7904_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) .detect = nct7904_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .address_list = normal_i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) module_i2c_driver(nct7904_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) MODULE_AUTHOR("Vadim V. Vlasov <vvlasov@dev.rtsoft.ru>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) MODULE_DESCRIPTION("Hwmon driver for NUVOTON NCT7904");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) MODULE_LICENSE("GPL");