brintos

brintos / linux-shallow public Read only

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