📄 dme1737.c
字号:
{ return PWM_RR_FROM_REG(reg, ix) ? 1 : 0;}static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg){ int en = (ix == 1) ? 0x80 : 0x08; return val ? reg | en : reg & ~en;}/* PWM min/off * The PWM min/off bits are part of the PMW ramp rate register 0 (see above for * the register layout). */static inline int PWM_OFF_FROM_REG(int reg, int ix){ return (reg >> (ix + 5)) & 0x01;}static inline int PWM_OFF_TO_REG(int val, int ix, int reg){ return (reg & ~(1 << (ix + 5))) | ((val & 0x01) << (ix + 5));}/* --------------------------------------------------------------------- * Device I/O access * * ISA access is performed through an index/data register pair and needs to * be protected by a mutex during runtime (not required for initialization). * We use data->update_lock for this and need to ensure that we acquire it * before calling dme1737_read or dme1737_write. * --------------------------------------------------------------------- */static u8 dme1737_read(struct i2c_client *client, u8 reg){ s32 val; if (client->driver) { /* I2C device */ val = i2c_smbus_read_byte_data(client, reg); if (val < 0) { dev_warn(&client->dev, "Read from register " "0x%02x failed! Please report to the driver " "maintainer.\n", reg); } } else { /* ISA device */ outb(reg, client->addr); val = inb(client->addr + 1); } return val;}static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val){ s32 res = 0; if (client->driver) { /* I2C device */ res = i2c_smbus_write_byte_data(client, reg, val); if (res < 0) { dev_warn(&client->dev, "Write to register " "0x%02x failed! Please report to the driver " "maintainer.\n", reg); } } else { /* ISA device */ outb(reg, client->addr); outb(val, client->addr + 1); } return res;}static struct dme1737_data *dme1737_update_device(struct device *dev){ struct dme1737_data *data = dev_get_drvdata(dev); struct i2c_client *client = &data->client; int ix; u8 lsb[5]; mutex_lock(&data->update_lock); /* Enable a Vbat monitoring cycle every 10 mins */ if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) { dme1737_write(client, DME1737_REG_CONFIG, dme1737_read(client, DME1737_REG_CONFIG) | 0x10); data->last_vbat = jiffies; } /* Sample register contents every 1 sec */ if (time_after(jiffies, data->last_update + HZ) || !data->valid) { data->vid = dme1737_read(client, DME1737_REG_VID) & 0x3f; /* In (voltage) registers */ for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { /* Voltage inputs are stored as 16 bit values even * though they have only 12 bits resolution. This is * to make it consistent with the temp inputs. */ data->in[ix] = dme1737_read(client, DME1737_REG_IN(ix)) << 8; data->in_min[ix] = dme1737_read(client, DME1737_REG_IN_MIN(ix)); data->in_max[ix] = dme1737_read(client, DME1737_REG_IN_MAX(ix)); } /* Temp registers */ for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { /* Temp inputs are stored as 16 bit values even * though they have only 12 bits resolution. This is * to take advantage of implicit conversions between * register values (2's complement) and temp values * (signed decimal). */ data->temp[ix] = dme1737_read(client, DME1737_REG_TEMP(ix)) << 8; data->temp_min[ix] = dme1737_read(client, DME1737_REG_TEMP_MIN(ix)); data->temp_max[ix] = dme1737_read(client, DME1737_REG_TEMP_MAX(ix)); data->temp_offset[ix] = dme1737_read(client, DME1737_REG_TEMP_OFFSET(ix)); } /* In and temp LSB registers * The LSBs are latched when the MSBs are read, so the order in * which the registers are read (MSB first, then LSB) is * important! */ for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { lsb[ix] = dme1737_read(client, DME1737_REG_IN_TEMP_LSB(ix)); } for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] << DME1737_REG_IN_LSB_SHL[ix]) & 0xf0; } for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { data->temp[ix] |= (lsb[DME1737_REG_TEMP_LSB[ix]] << DME1737_REG_TEMP_LSB_SHL[ix]) & 0xf0; } /* Fan registers */ for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { /* Skip reading registers if optional fans are not * present */ if (!(data->has_fan & (1 << ix))) { continue; } data->fan[ix] = dme1737_read(client, DME1737_REG_FAN(ix)); data->fan[ix] |= dme1737_read(client, DME1737_REG_FAN(ix) + 1) << 8; data->fan_min[ix] = dme1737_read(client, DME1737_REG_FAN_MIN(ix)); data->fan_min[ix] |= dme1737_read(client, DME1737_REG_FAN_MIN(ix) + 1) << 8; data->fan_opt[ix] = dme1737_read(client, DME1737_REG_FAN_OPT(ix)); /* fan_max exists only for fan[5-6] */ if (ix > 3) { data->fan_max[ix - 4] = dme1737_read(client, DME1737_REG_FAN_MAX(ix)); } } /* PWM registers */ for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) { /* Skip reading registers if optional PWMs are not * present */ if (!(data->has_pwm & (1 << ix))) { continue; } data->pwm[ix] = dme1737_read(client, DME1737_REG_PWM(ix)); data->pwm_freq[ix] = dme1737_read(client, DME1737_REG_PWM_FREQ(ix)); /* pwm_config and pwm_min exist only for pwm[1-3] */ if (ix < 3) { data->pwm_config[ix] = dme1737_read(client, DME1737_REG_PWM_CONFIG(ix)); data->pwm_min[ix] = dme1737_read(client, DME1737_REG_PWM_MIN(ix)); } } for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) { data->pwm_rr[ix] = dme1737_read(client, DME1737_REG_PWM_RR(ix)); } /* Thermal zone registers */ for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) { data->zone_low[ix] = dme1737_read(client, DME1737_REG_ZONE_LOW(ix)); data->zone_abs[ix] = dme1737_read(client, DME1737_REG_ZONE_ABS(ix)); } for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { data->zone_hyst[ix] = dme1737_read(client, DME1737_REG_ZONE_HYST(ix)); } /* Alarm registers */ data->alarms = dme1737_read(client, DME1737_REG_ALARM1); /* Bit 7 tells us if the other alarm registers are non-zero and * therefore also need to be read */ if (data->alarms & 0x80) { data->alarms |= dme1737_read(client, DME1737_REG_ALARM2) << 8; data->alarms |= dme1737_read(client, DME1737_REG_ALARM3) << 16; } /* The ISA chips require explicit clearing of alarm bits. * Don't worry, an alarm will come back if the condition * that causes it still exists */ if (!client->driver) { if (data->alarms & 0xff0000) { dme1737_write(client, DME1737_REG_ALARM3, 0xff); } if (data->alarms & 0xff00) { dme1737_write(client, DME1737_REG_ALARM2, 0xff); } if (data->alarms & 0xff) { dme1737_write(client, DME1737_REG_ALARM1, 0xff); } } data->last_update = jiffies; data->valid = 1; } mutex_unlock(&data->update_lock); return data;}/* --------------------------------------------------------------------- * Voltage sysfs attributes * ix = [0-5] * --------------------------------------------------------------------- */#define SYS_IN_INPUT 0#define SYS_IN_MIN 1#define SYS_IN_MAX 2#define SYS_IN_ALARM 3static ssize_t show_in(struct device *dev, struct device_attribute *attr, char *buf){ struct dme1737_data *data = dme1737_update_device(dev); struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; int fn = sensor_attr_2->nr; int res; switch (fn) { case SYS_IN_INPUT: res = IN_FROM_REG(data->in[ix], ix, 16); break; case SYS_IN_MIN: res = IN_FROM_REG(data->in_min[ix], ix, 8); break; case SYS_IN_MAX: res = IN_FROM_REG(data->in_max[ix], ix, 8); break; case SYS_IN_ALARM: res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01; break; default: res = 0; dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res);}static ssize_t set_in(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct dme1737_data *data = dev_get_drvdata(dev); struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; int fn = sensor_attr_2->nr; long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); switch (fn) { case SYS_IN_MIN: data->in_min[ix] = IN_TO_REG(val, ix); dme1737_write(client, DME1737_REG_IN_MIN(ix), data->in_min[ix]); break; case SYS_IN_MAX: data->in_max[ix] = IN_TO_REG(val, ix); dme1737_write(client, DME1737_REG_IN_MAX(ix), data->in_max[ix]); break; default: dev_dbg(dev, "Unknown function %d.\n", fn); } mutex_unlock(&data->update_lock); return count;}/* --------------------------------------------------------------------- * Temperature sysfs attributes * ix = [0-2] * --------------------------------------------------------------------- */#define SYS_TEMP_INPUT 0#define SYS_TEMP_MIN 1#define SYS_TEMP_MAX 2#define SYS_TEMP_OFFSET 3#define SYS_TEMP_ALARM 4#define SYS_TEMP_FAULT 5static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf){ struct dme1737_data *data = dme1737_update_device(dev); struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; int fn = sensor_attr_2->nr; int res; switch (fn) { case SYS_TEMP_INPUT: res = TEMP_FROM_REG(data->temp[ix], 16); break; case SYS_TEMP_MIN: res = TEMP_FROM_REG(data->temp_min[ix], 8); break; case SYS_TEMP_MAX: res = TEMP_FROM_REG(data->temp_max[ix], 8); break; case SYS_TEMP_OFFSET: res = TEMP_FROM_REG(data->temp_offset[ix], 8); break; case SYS_TEMP_ALARM: res = (data->alarms >> DME1737_BIT_ALARM_TEMP[ix]) & 0x01; break; case SYS_TEMP_FAULT: res = (((u16)data->temp[ix] & 0xff00) == 0x8000); break; default: res = 0; dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res);}static ssize_t set_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct dme1737_data *data = dev_get_drvdata(dev); struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; int fn = sensor_attr_2->nr; long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); switch (fn) { case SYS_TEMP_MIN: data->temp_min[ix] = TEMP_TO_REG(val); dme1737_write(client, DME1737_REG_TEMP_MIN(ix), data->temp_min[ix]); break; case SYS_TEMP_MAX: data->temp_max[ix] = TEMP_TO_REG(val); dme1737_write(client, DME1737_REG_TEMP_MAX(ix), data->temp_max[ix]); break; case SYS_TEMP_OFFSET: data->temp_offset[ix] = TEMP_TO_REG(val); dme1737_write(client, DME1737_REG_TEMP_OFFSET(ix), data->temp_offset[ix]); break; default: dev_dbg(dev, "Unknown function %d.\n", fn); } mutex_unlock(&data->update_lock); return count;}/* --------------------------------------------------------------------- * Zone sysfs attributes * ix = [0-2] * --------------------------------------------------------------------- */#define SYS_ZONE_AUTO_CHANNELS_TEMP 0#define SYS_ZONE_AUTO_POINT1_TEMP_HYST 1#define SYS_ZONE_AUTO_POINT1_TEMP 2#define SYS_ZONE_AUTO_POINT2_TEMP 3#define SYS_ZONE_AUTO_POINT3_TEMP 4static ssize_t show_zone(struct device *dev, struct device_attribute *attr, char *buf){ struct dme1737_data *data = dme1737_update_device(dev); struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; int fn = sensor_attr_2->nr; int res; switch (fn) { case SYS_ZONE_AUTO_CHANNELS_TEMP: /* check config2 for non-standard temp-to-zone mapping */ if ((ix == 1) && (data->config2 & 0x02)) { res = 4; } else { res = 1 << ix; } break; case SYS_ZONE_AUTO_POINT1_TEMP_HYST: res = TEMP_FROM_REG(data->zone_low[ix], 8) - TEMP_HYST_FROM_REG(data->zone_hyst[ix == 2], ix); break; case SYS_ZONE_AUTO_POINT1_TEMP: res = TEMP_FROM_REG(data->zone_low[ix], 8); break; case SYS_ZONE_AUTO_POINT2_TEMP: /* pwm_freq holds the temp range bits in the upper nibble */ res = TEMP_FROM_REG(data->zone_low[ix], 8) + TEMP_RANGE_FROM_REG(data->pwm_freq[ix]); break; case SYS_ZONE_AUTO_POINT3_TEMP: res = TEMP_FROM_REG(data->zone_abs[ix], 8); break; default: res = 0; dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res);}static ssize_t set_zone(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -