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 + -
显示快捷键?