📄 dme1737.c
字号:
/* * dme1737.c - Driver for the SMSC DME1737, Asus A8000, and SMSC SCH311x * Super-I/O chips integrated hardware monitoring features. * Copyright (c) 2007 Juerg Haefliger <juergh@gmail.com> * * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access * the chip registers if a DME1737 (or A8000) is found and the ISA bus if a * SCH311x chip is found. Both types of chips have very similar hardware * monitoring capabilities but differ in the way they can be accessed. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/jiffies.h>#include <linux/i2c.h>#include <linux/platform_device.h>#include <linux/hwmon.h>#include <linux/hwmon-sysfs.h>#include <linux/hwmon-vid.h>#include <linux/err.h>#include <linux/mutex.h>#include <asm/io.h>/* ISA device, if found */static struct platform_device *pdev;/* Module load parameters */static int force_start;module_param(force_start, bool, 0);MODULE_PARM_DESC(force_start, "Force the chip to start monitoring inputs");/* Addresses to scan */static unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};/* Insmod parameters */I2C_CLIENT_INSMOD_1(dme1737);/* --------------------------------------------------------------------- * Registers * * The sensors are defined as follows: * * Voltages Temperatures * -------- ------------ * in0 +5VTR (+5V stdby) temp1 Remote diode 1 * in1 Vccp (proc core) temp2 Internal temp * in2 VCC (internal +3.3V) temp3 Remote diode 2 * in3 +5V * in4 +12V * in5 VTR (+3.3V stby) * in6 Vbat * * --------------------------------------------------------------------- *//* Voltages (in) numbered 0-6 (ix) */#define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) \ : 0x94 + (ix))#define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \ : 0x91 + (ix) * 2)#define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \ : 0x92 + (ix) * 2)/* Temperatures (temp) numbered 0-2 (ix) */#define DME1737_REG_TEMP(ix) (0x25 + (ix))#define DME1737_REG_TEMP_MIN(ix) (0x4e + (ix) * 2)#define DME1737_REG_TEMP_MAX(ix) (0x4f + (ix) * 2)#define DME1737_REG_TEMP_OFFSET(ix) ((ix) == 0 ? 0x1f \ : 0x1c + (ix))/* Voltage and temperature LSBs * The LSBs (4 bits each) are stored in 5 registers with the following layouts: * IN_TEMP_LSB(0) = [in5, in6] * IN_TEMP_LSB(1) = [temp3, temp1] * IN_TEMP_LSB(2) = [in4, temp2] * IN_TEMP_LSB(3) = [in3, in0] * IN_TEMP_LSB(4) = [in2, in1] */#define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix))static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0};static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4};static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1};static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0};/* Fans numbered 0-5 (ix) */#define DME1737_REG_FAN(ix) ((ix) < 4 ? 0x28 + (ix) * 2 \ : 0xa1 + (ix) * 2)#define DME1737_REG_FAN_MIN(ix) ((ix) < 4 ? 0x54 + (ix) * 2 \ : 0xa5 + (ix) * 2)#define DME1737_REG_FAN_OPT(ix) ((ix) < 4 ? 0x90 + (ix) \ : 0xb2 + (ix))#define DME1737_REG_FAN_MAX(ix) (0xb4 + (ix)) /* only for fan[4-5] *//* PWMs numbered 0-2, 4-5 (ix) */#define DME1737_REG_PWM(ix) ((ix) < 3 ? 0x30 + (ix) \ : 0xa1 + (ix))#define DME1737_REG_PWM_CONFIG(ix) (0x5c + (ix)) /* only for pwm[0-2] */#define DME1737_REG_PWM_MIN(ix) (0x64 + (ix)) /* only for pwm[0-2] */#define DME1737_REG_PWM_FREQ(ix) ((ix) < 3 ? 0x5f + (ix) \ : 0xa3 + (ix))/* The layout of the ramp rate registers is different from the other pwm * registers. The bits for the 3 PWMs are stored in 2 registers: * PWM_RR(0) = [OFF3, OFF2, OFF1, RES, RR1E, RR1-2, RR1-1, RR1-0] * PWM_RR(1) = [RR2E, RR2-2, RR2-1, RR2-0, RR3E, RR3-2, RR3-1, RR3-0] */#define DME1737_REG_PWM_RR(ix) (0x62 + (ix)) /* only for pwm[0-2] *//* Thermal zones 0-2 */#define DME1737_REG_ZONE_LOW(ix) (0x67 + (ix))#define DME1737_REG_ZONE_ABS(ix) (0x6a + (ix))/* The layout of the hysteresis registers is different from the other zone * registers. The bits for the 3 zones are stored in 2 registers: * ZONE_HYST(0) = [H1-3, H1-2, H1-1, H1-0, H2-3, H2-2, H2-1, H2-0] * ZONE_HYST(1) = [H3-3, H3-2, H3-1, H3-0, RES, RES, RES, RES] */#define DME1737_REG_ZONE_HYST(ix) (0x6d + (ix))/* Alarm registers and bit mapping * The 3 8-bit alarm registers will be concatenated to a single 32-bit * alarm value [0, ALARM3, ALARM2, ALARM1]. */#define DME1737_REG_ALARM1 0x41#define DME1737_REG_ALARM2 0x42#define DME1737_REG_ALARM3 0x83static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17};static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6};static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};/* Miscellaneous registers */#define DME1737_REG_DEVICE 0x3d#define DME1737_REG_COMPANY 0x3e#define DME1737_REG_VERSTEP 0x3f#define DME1737_REG_CONFIG 0x40#define DME1737_REG_CONFIG2 0x7f#define DME1737_REG_VID 0x43#define DME1737_REG_TACH_PWM 0x81/* --------------------------------------------------------------------- * Misc defines * --------------------------------------------------------------------- *//* Chip identification */#define DME1737_COMPANY_SMSC 0x5c#define DME1737_VERSTEP 0x88#define DME1737_VERSTEP_MASK 0xf8#define SCH311X_DEVICE 0x8c/* Length of ISA address segment */#define DME1737_EXTENT 2/* --------------------------------------------------------------------- * Data structures and manipulation thereof * --------------------------------------------------------------------- *//* For ISA chips, we abuse the i2c_client addr and name fields. We also use the driver field to differentiate between I2C and ISA chips. */struct dme1737_data { struct i2c_client client; struct device *hwmon_dev; struct mutex update_lock; int valid; /* !=0 if following fields are valid */ unsigned long last_update; /* in jiffies */ unsigned long last_vbat; /* in jiffies */ u8 vid; u8 pwm_rr_en; u8 has_pwm; u8 has_fan; /* Register values */ u16 in[7]; u8 in_min[7]; u8 in_max[7]; s16 temp[3]; s8 temp_min[3]; s8 temp_max[3]; s8 temp_offset[3]; u8 config; u8 config2; u8 vrm; u16 fan[6]; u16 fan_min[6]; u8 fan_max[2]; u8 fan_opt[6]; u8 pwm[6]; u8 pwm_min[3]; u8 pwm_config[3]; u8 pwm_acz[3]; u8 pwm_freq[6]; u8 pwm_rr[2]; u8 zone_low[3]; u8 zone_abs[3]; u8 zone_hyst[2]; u32 alarms;};/* Nominal voltage values */static const int IN_NOMINAL[] = {5000, 2250, 3300, 5000, 12000, 3300, 3300};/* Voltage input * Voltage inputs have 16 bits resolution, limit values have 8 bits * resolution. */static inline int IN_FROM_REG(int reg, int ix, int res){ return (reg * IN_NOMINAL[ix] + (3 << (res - 3))) / (3 << (res - 2));}static inline int IN_TO_REG(int val, int ix){ return SENSORS_LIMIT((val * 192 + IN_NOMINAL[ix] / 2) / IN_NOMINAL[ix], 0, 255);}/* Temperature input * The register values represent temperatures in 2's complement notation from * -127 degrees C to +127 degrees C. Temp inputs have 16 bits resolution, limit * values have 8 bits resolution. */static inline int TEMP_FROM_REG(int reg, int res){ return (reg * 1000) >> (res - 8);}static inline int TEMP_TO_REG(int val){ return SENSORS_LIMIT((val < 0 ? val - 500 : val + 500) / 1000, -128, 127);}/* Temperature range */static const int TEMP_RANGE[] = {2000, 2500, 3333, 4000, 5000, 6666, 8000, 10000, 13333, 16000, 20000, 26666, 32000, 40000, 53333, 80000};static inline int TEMP_RANGE_FROM_REG(int reg){ return TEMP_RANGE[(reg >> 4) & 0x0f];}static int TEMP_RANGE_TO_REG(int val, int reg){ int i; for (i = 15; i > 0; i--) { if (val > (TEMP_RANGE[i] + TEMP_RANGE[i - 1] + 1) / 2) { break; } } return (reg & 0x0f) | (i << 4);}/* Temperature hysteresis * Register layout: * reg[0] = [H1-3, H1-2, H1-1, H1-0, H2-3, H2-2, H2-1, H2-0] * reg[1] = [H3-3, H3-2, H3-1, H3-0, xxxx, xxxx, xxxx, xxxx] */static inline int TEMP_HYST_FROM_REG(int reg, int ix){ return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000;}static inline int TEMP_HYST_TO_REG(int val, int ix, int reg){ int hyst = SENSORS_LIMIT((val + 500) / 1000, 0, 15); return (ix == 1) ? (reg & 0xf0) | hyst : (reg & 0x0f) | (hyst << 4);}/* Fan input RPM */static inline int FAN_FROM_REG(int reg, int tpc){ return (reg == 0 || reg == 0xffff) ? 0 : (tpc == 0) ? 90000 * 60 / reg : tpc * reg;}static inline int FAN_TO_REG(int val, int tpc){ return SENSORS_LIMIT((tpc == 0) ? 90000 * 60 / val : val / tpc, 0, 0xffff);}/* Fan TPC (tach pulse count) * Converts a register value to a TPC multiplier or returns 0 if the tachometer * is configured in legacy (non-tpc) mode */static inline int FAN_TPC_FROM_REG(int reg){ return (reg & 0x20) ? 0 : 60 >> (reg & 0x03);}/* Fan type * The type of a fan is expressed in number of pulses-per-revolution that it * emits */static inline int FAN_TYPE_FROM_REG(int reg){ int edge = (reg >> 1) & 0x03; return (edge > 0) ? 1 << (edge - 1) : 0;}static inline int FAN_TYPE_TO_REG(int val, int reg){ int edge = (val == 4) ? 3 : val; return (reg & 0xf9) | (edge << 1);}/* Fan max RPM */static const int FAN_MAX[] = {0x54, 0x38, 0x2a, 0x21, 0x1c, 0x18, 0x15, 0x12, 0x11, 0x0f, 0x0e};static int FAN_MAX_FROM_REG(int reg){ int i; for (i = 10; i > 0; i--) { if (reg == FAN_MAX[i]) { break; } } return 1000 + i * 500;}static int FAN_MAX_TO_REG(int val){ int i; for (i = 10; i > 0; i--) { if (val > (1000 + (i - 1) * 500)) { break; } } return FAN_MAX[i];}/* PWM enable * Register to enable mapping: * 000: 2 fan on zone 1 auto * 001: 2 fan on zone 2 auto * 010: 2 fan on zone 3 auto * 011: 0 fan full on * 100: -1 fan disabled * 101: 2 fan on hottest of zones 2,3 auto * 110: 2 fan on hottest of zones 1,2,3 auto * 111: 1 fan in manual mode */static inline int PWM_EN_FROM_REG(int reg){ static const int en[] = {2, 2, 2, 0, -1, 2, 2, 1}; return en[(reg >> 5) & 0x07];}static inline int PWM_EN_TO_REG(int val, int reg){ int en = (val == 1) ? 7 : 3; return (reg & 0x1f) | ((en & 0x07) << 5);}/* PWM auto channels zone * Register to auto channels zone mapping (ACZ is a bitfield with bit x * corresponding to zone x+1): * 000: 001 fan on zone 1 auto * 001: 010 fan on zone 2 auto * 010: 100 fan on zone 3 auto * 011: 000 fan full on * 100: 000 fan disabled * 101: 110 fan on hottest of zones 2,3 auto * 110: 111 fan on hottest of zones 1,2,3 auto * 111: 000 fan in manual mode */static inline int PWM_ACZ_FROM_REG(int reg){ static const int acz[] = {1, 2, 4, 0, 0, 6, 7, 0}; return acz[(reg >> 5) & 0x07];}static inline int PWM_ACZ_TO_REG(int val, int reg){ int acz = (val == 4) ? 2 : val - 1; return (reg & 0x1f) | ((acz & 0x07) << 5);}/* PWM frequency */static const int PWM_FREQ[] = {11, 15, 22, 29, 35, 44, 59, 88, 15000, 20000, 30000, 25000, 0, 0, 0, 0};static inline int PWM_FREQ_FROM_REG(int reg){ return PWM_FREQ[reg & 0x0f];}static int PWM_FREQ_TO_REG(int val, int reg){ int i; /* the first two cases are special - stupid chip design! */ if (val > 27500) { i = 10; } else if (val > 22500) { i = 11; } else { for (i = 9; i > 0; i--) { if (val > (PWM_FREQ[i] + PWM_FREQ[i - 1] + 1) / 2) { break; } } } return (reg & 0xf0) | i;}/* PWM ramp rate * Register layout: * reg[0] = [OFF3, OFF2, OFF1, RES, RR1-E, RR1-2, RR1-1, RR1-0] * reg[1] = [RR2-E, RR2-2, RR2-1, RR2-0, RR3-E, RR3-2, RR3-1, RR3-0] */static const u8 PWM_RR[] = {206, 104, 69, 41, 26, 18, 10, 5};static inline int PWM_RR_FROM_REG(int reg, int ix){ int rr = (ix == 1) ? reg >> 4 : reg; return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0;}static int PWM_RR_TO_REG(int val, int ix, int reg){ int i; for (i = 0; i < 7; i++) { if (val > (PWM_RR[i] + PWM_RR[i + 1] + 1) / 2) { break; } } return (ix == 1) ? (reg & 0x8f) | (i << 4) : (reg & 0xf8) | i;}/* PWM ramp rate enable */static inline int PWM_RR_EN_FROM_REG(int reg, int ix)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -