lm93.c

来自「linux 内核源代码」· C语言 代码 · 共 2,063 行 · 第 1/5 页

C
2,063
字号
/* TEMP: 1/1000 degrees C (-128C to +127C)   REG: 1C/bit, two's complement */static u8 LM93_TEMP_TO_REG(long temp){	int ntemp = SENSORS_LIMIT(temp, LM93_TEMP_MIN, LM93_TEMP_MAX);	ntemp += (ntemp<0 ? -500 : 500);	return (u8)(ntemp / 1000);}/* Determine 4-bit temperature offset resolution */static int LM93_TEMP_OFFSET_MODE_FROM_REG(u8 sfc2, int nr){	/* mode: 0 => 1C/bit, nonzero => 0.5C/bit */	return sfc2 & (nr < 2 ? 0x10 : 0x20);}/* This function is common to all 4-bit temperature offsets   reg is 4 bits right justified   mode 0 => 1C/bit, mode !0 => 0.5C/bit */static int LM93_TEMP_OFFSET_FROM_REG(u8 reg, int mode){	return (reg & 0x0f) * (mode ? 5 : 10);}#define LM93_TEMP_OFFSET_MIN  (  0)#define LM93_TEMP_OFFSET_MAX0 (150)#define LM93_TEMP_OFFSET_MAX1 ( 75)/* This function is common to all 4-bit temperature offsets   returns 4 bits right justified   mode 0 => 1C/bit, mode !0 => 0.5C/bit */static u8 LM93_TEMP_OFFSET_TO_REG(int off, int mode){	int factor = mode ? 5 : 10;	off = SENSORS_LIMIT(off, LM93_TEMP_OFFSET_MIN,		mode ? LM93_TEMP_OFFSET_MAX1 : LM93_TEMP_OFFSET_MAX0);	return (u8)((off + factor/2) / factor);}/* 0 <= nr <= 3 */static int LM93_TEMP_AUTO_OFFSET_FROM_REG(u8 reg, int nr, int mode){	/* temp1-temp2 (nr=0,1) use lower nibble */	if (nr < 2)		return LM93_TEMP_OFFSET_FROM_REG(reg & 0x0f, mode);	/* temp3-temp4 (nr=2,3) use upper nibble */	else		return LM93_TEMP_OFFSET_FROM_REG(reg >> 4 & 0x0f, mode);}/* TEMP: 1/10 degrees C (0C to +15C (mode 0) or +7.5C (mode non-zero))   REG: 1.0C/bit (mode 0) or 0.5C/bit (mode non-zero)   0 <= nr <= 3 */static u8 LM93_TEMP_AUTO_OFFSET_TO_REG(u8 old, int off, int nr, int mode){	u8 new = LM93_TEMP_OFFSET_TO_REG(off, mode);	/* temp1-temp2 (nr=0,1) use lower nibble */	if (nr < 2)		return (old & 0xf0) | (new & 0x0f);	/* temp3-temp4 (nr=2,3) use upper nibble */	else		return (new << 4 & 0xf0) | (old & 0x0f);}static int LM93_AUTO_BOOST_HYST_FROM_REGS(struct lm93_data *data, int nr,		int mode){	u8 reg;	switch (nr) {	case 0:		reg = data->boost_hyst[0] & 0x0f;		break;	case 1:		reg = data->boost_hyst[0] >> 4 & 0x0f;		break;	case 2:		reg = data->boost_hyst[1] & 0x0f;		break;	case 3:	default:		reg = data->boost_hyst[1] >> 4 & 0x0f;		break;	}	return LM93_TEMP_FROM_REG(data->boost[nr]) -			LM93_TEMP_OFFSET_FROM_REG(reg, mode);}static u8 LM93_AUTO_BOOST_HYST_TO_REG(struct lm93_data *data, long hyst,		int nr, int mode){	u8 reg = LM93_TEMP_OFFSET_TO_REG(			(LM93_TEMP_FROM_REG(data->boost[nr]) - hyst), mode);	switch (nr) {	case 0:		reg = (data->boost_hyst[0] & 0xf0) | (reg & 0x0f);		break;	case 1:		reg = (reg << 4 & 0xf0) | (data->boost_hyst[0] & 0x0f);		break;	case 2:		reg = (data->boost_hyst[1] & 0xf0) | (reg & 0x0f);		break;	case 3:	default:		reg = (reg << 4 & 0xf0) | (data->boost_hyst[1] & 0x0f);		break;	}	return reg;}/* PWM: 0-255 per sensors documentation   REG: 0-13 as mapped below... right justified */typedef enum { LM93_PWM_MAP_HI_FREQ, LM93_PWM_MAP_LO_FREQ } pwm_freq_t;static int lm93_pwm_map[2][16] = {	{		0x00, /*   0.00% */ 0x40, /*  25.00% */		0x50, /*  31.25% */ 0x60, /*  37.50% */		0x70, /*  43.75% */ 0x80, /*  50.00% */		0x90, /*  56.25% */ 0xa0, /*  62.50% */		0xb0, /*  68.75% */ 0xc0, /*  75.00% */		0xd0, /*  81.25% */ 0xe0, /*  87.50% */		0xf0, /*  93.75% */ 0xff, /* 100.00% */		0xff, 0xff, /* 14, 15 are reserved and should never occur */	},	{		0x00, /*   0.00% */ 0x40, /*  25.00% */		0x49, /*  28.57% */ 0x52, /*  32.14% */		0x5b, /*  35.71% */ 0x64, /*  39.29% */		0x6d, /*  42.86% */ 0x76, /*  46.43% */		0x80, /*  50.00% */ 0x89, /*  53.57% */		0x92, /*  57.14% */ 0xb6, /*  71.43% */		0xdb, /*  85.71% */ 0xff, /* 100.00% */		0xff, 0xff, /* 14, 15 are reserved and should never occur */	},};static int LM93_PWM_FROM_REG(u8 reg, pwm_freq_t freq){	return lm93_pwm_map[freq][reg & 0x0f];}/* round up to nearest match */static u8 LM93_PWM_TO_REG(int pwm, pwm_freq_t freq){	int i;	for (i = 0; i < 13; i++)		if (pwm <= lm93_pwm_map[freq][i])			break;	/* can fall through with i==13 */	return (u8)i;}static int LM93_FAN_FROM_REG(u16 regs){	const u16 count = le16_to_cpu(regs) >> 2;	return count==0 ? -1 : count==0x3fff ? 0: 1350000 / count;}/* * RPM: (82.5 to 1350000) * REG: 14-bits, LE, *left* justified */static u16 LM93_FAN_TO_REG(long rpm){	u16 count, regs;	if (rpm == 0) {		count = 0x3fff;	} else {		rpm = SENSORS_LIMIT(rpm, 1, 1000000);		count = SENSORS_LIMIT((1350000 + rpm) / rpm, 1, 0x3ffe);	}	regs = count << 2;	return cpu_to_le16(regs);}/* PWM FREQ: HZ   REG: 0-7 as mapped below */static int lm93_pwm_freq_map[8] = {	22500, 96, 84, 72, 60, 48, 36, 12};static int LM93_PWM_FREQ_FROM_REG(u8 reg){	return lm93_pwm_freq_map[reg & 0x07];}/* round up to nearest match */static u8 LM93_PWM_FREQ_TO_REG(int freq){	int i;	for (i = 7; i > 0; i--)		if (freq <= lm93_pwm_freq_map[i])			break;	/* can fall through with i==0 */	return (u8)i;}/* TIME: 1/100 seconds * REG: 0-7 as mapped below */static int lm93_spinup_time_map[8] = {	0, 10, 25, 40, 70, 100, 200, 400,};static int LM93_SPINUP_TIME_FROM_REG(u8 reg){	return lm93_spinup_time_map[reg >> 5 & 0x07];}/* round up to nearest match */static u8 LM93_SPINUP_TIME_TO_REG(int time){	int i;	for (i = 0; i < 7; i++)		if (time <= lm93_spinup_time_map[i])			break;	/* can fall through with i==8 */	return (u8)i;}#define LM93_RAMP_MIN 0#define LM93_RAMP_MAX 75static int LM93_RAMP_FROM_REG(u8 reg){	return (reg & 0x0f) * 5;}/* RAMP: 1/100 seconds   REG: 50mS/bit 4-bits right justified */static u8 LM93_RAMP_TO_REG(int ramp){	ramp = SENSORS_LIMIT(ramp, LM93_RAMP_MIN, LM93_RAMP_MAX);	return (u8)((ramp + 2) / 5);}/* PROCHOT: 0-255, 0 => 0%, 255 => > 96.6% * REG: (same) */static u8 LM93_PROCHOT_TO_REG(long prochot){	prochot = SENSORS_LIMIT(prochot, 0, 255);	return (u8)prochot;}/* PROCHOT-INTERVAL: 73 - 37200 (1/100 seconds) * REG: 0-9 as mapped below */static int lm93_interval_map[10] = {	73, 146, 290, 580, 1170, 2330, 4660, 9320, 18600, 37200,};static int LM93_INTERVAL_FROM_REG(u8 reg){	return lm93_interval_map[reg & 0x0f];}/* round up to nearest match */static u8 LM93_INTERVAL_TO_REG(long interval){	int i;	for (i = 0; i < 9; i++)		if (interval <= lm93_interval_map[i])			break;	/* can fall through with i==9 */	return (u8)i;}/* GPIO: 0-255, GPIO0 is LSB * REG: inverted */static unsigned LM93_GPI_FROM_REG(u8 reg){	return ~reg & 0xff;}/* alarm bitmask definitions   The LM93 has nearly 64 bits of error status... I've pared that down to   what I think is a useful subset in order to fit it into 32 bits.   Especially note that the #VRD_HOT alarms are missing because we provide   that information as values in another sysfs file.   If libsensors is extended to support 64 bit values, this could be revisited.*/#define LM93_ALARM_IN1		0x00000001#define LM93_ALARM_IN2		0x00000002#define LM93_ALARM_IN3		0x00000004#define LM93_ALARM_IN4		0x00000008#define LM93_ALARM_IN5		0x00000010#define LM93_ALARM_IN6		0x00000020#define LM93_ALARM_IN7		0x00000040#define LM93_ALARM_IN8		0x00000080#define LM93_ALARM_IN9		0x00000100#define LM93_ALARM_IN10		0x00000200#define LM93_ALARM_IN11		0x00000400#define LM93_ALARM_IN12		0x00000800#define LM93_ALARM_IN13		0x00001000#define LM93_ALARM_IN14		0x00002000#define LM93_ALARM_IN15		0x00004000#define LM93_ALARM_IN16		0x00008000#define LM93_ALARM_FAN1		0x00010000#define LM93_ALARM_FAN2		0x00020000#define LM93_ALARM_FAN3		0x00040000#define LM93_ALARM_FAN4		0x00080000#define LM93_ALARM_PH1_ERR	0x00100000#define LM93_ALARM_PH2_ERR	0x00200000#define LM93_ALARM_SCSI1_ERR	0x00400000#define LM93_ALARM_SCSI2_ERR	0x00800000#define LM93_ALARM_DVDDP1_ERR	0x01000000#define LM93_ALARM_DVDDP2_ERR	0x02000000#define LM93_ALARM_D1_ERR	0x04000000#define LM93_ALARM_D2_ERR	0x08000000#define LM93_ALARM_TEMP1	0x10000000#define LM93_ALARM_TEMP2	0x20000000#define LM93_ALARM_TEMP3	0x40000000static unsigned LM93_ALARMS_FROM_REG(struct block1_t b1){	unsigned result;	result  = b1.host_status_2 & 0x3f;	if (vccp_limit_type[0])		result |= (b1.host_status_4 & 0x10) << 2;	else		result |= b1.host_status_2 & 0x40;	if (vccp_limit_type[1])		result |= (b1.host_status_4 & 0x20) << 2;	else		result |= b1.host_status_2 & 0x80;	result |= b1.host_status_3 << 8;	result |= (b1.fan_status & 0x0f) << 16;	result |= (b1.p1_prochot_status & 0x80) << 13;	result |= (b1.p2_prochot_status & 0x80) << 14;	result |= (b1.host_status_4 & 0xfc) << 20;	result |= (b1.host_status_1 & 0x07) << 28;	return result;}#define MAX_RETRIES 5static u8 lm93_read_byte(struct i2c_client *client, u8 reg){	int value, i;	/* retry in case of read errors */	for (i=1; i<=MAX_RETRIES; i++) {		if ((value = i2c_smbus_read_byte_data(client, reg)) >= 0) {			return value;		} else {			dev_warn(&client->dev,"lm93: read byte data failed, "				"address 0x%02x.\n", reg);			mdelay(i + 3);		}	}	/* <TODO> what to return in case of error? */	dev_err(&client->dev,"lm93: All read byte retries failed!!\n");	return 0;}static int lm93_write_byte(struct i2c_client *client, u8 reg, u8 value){	int result;	/* <TODO> how to handle write errors? */	result = i2c_smbus_write_byte_data(client, reg, value);	if (result < 0)		dev_warn(&client->dev,"lm93: write byte data failed, "			 "0x%02x at address 0x%02x.\n", value, reg);	return result;}static u16 lm93_read_word(struct i2c_client *client, u8 reg){	int value, i;	/* retry in case of read errors */	for (i=1; i<=MAX_RETRIES; i++) {		if ((value = i2c_smbus_read_word_data(client, reg)) >= 0) {			return value;		} else {			dev_warn(&client->dev,"lm93: read word data failed, "				 "address 0x%02x.\n", reg);			mdelay(i + 3);		}	}	/* <TODO> what to return in case of error? */	dev_err(&client->dev,"lm93: All read word retries failed!!\n");	return 0;}static int lm93_write_word(struct i2c_client *client, u8 reg, u16 value){	int result;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?