📄 dme1737.c
字号:
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_ZONE_AUTO_POINT1_TEMP_HYST: /* Refresh the cache */ data->zone_low[ix] = dme1737_read(client, DME1737_REG_ZONE_LOW(ix)); /* Modify the temp hyst value */ data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG( TEMP_FROM_REG(data->zone_low[ix], 8) - val, ix, dme1737_read(client, DME1737_REG_ZONE_HYST(ix == 2))); dme1737_write(client, DME1737_REG_ZONE_HYST(ix == 2), data->zone_hyst[ix == 2]); break; case SYS_ZONE_AUTO_POINT1_TEMP: data->zone_low[ix] = TEMP_TO_REG(val); dme1737_write(client, DME1737_REG_ZONE_LOW(ix), data->zone_low[ix]); break; case SYS_ZONE_AUTO_POINT2_TEMP: /* Refresh the cache */ data->zone_low[ix] = dme1737_read(client, DME1737_REG_ZONE_LOW(ix)); /* Modify the temp range value (which is stored in the upper * nibble of the pwm_freq register) */ data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val - TEMP_FROM_REG(data->zone_low[ix], 8), dme1737_read(client, DME1737_REG_PWM_FREQ(ix))); dme1737_write(client, DME1737_REG_PWM_FREQ(ix), data->pwm_freq[ix]); break; case SYS_ZONE_AUTO_POINT3_TEMP: data->zone_abs[ix] = TEMP_TO_REG(val); dme1737_write(client, DME1737_REG_ZONE_ABS(ix), data->zone_abs[ix]); break; default: dev_dbg(dev, "Unknown function %d.\n", fn); } mutex_unlock(&data->update_lock); return count;}/* --------------------------------------------------------------------- * Fan sysfs attributes * ix = [0-5] * --------------------------------------------------------------------- */#define SYS_FAN_INPUT 0#define SYS_FAN_MIN 1#define SYS_FAN_MAX 2#define SYS_FAN_ALARM 3#define SYS_FAN_TYPE 4static ssize_t show_fan(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_FAN_INPUT: res = FAN_FROM_REG(data->fan[ix], ix < 4 ? 0 : FAN_TPC_FROM_REG(data->fan_opt[ix])); break; case SYS_FAN_MIN: res = FAN_FROM_REG(data->fan_min[ix], ix < 4 ? 0 : FAN_TPC_FROM_REG(data->fan_opt[ix])); break; case SYS_FAN_MAX: /* only valid for fan[5-6] */ res = FAN_MAX_FROM_REG(data->fan_max[ix - 4]); break; case SYS_FAN_ALARM: res = (data->alarms >> DME1737_BIT_ALARM_FAN[ix]) & 0x01; break; case SYS_FAN_TYPE: /* only valid for fan[1-4] */ res = FAN_TYPE_FROM_REG(data->fan_opt[ix]); break; default: res = 0; dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res);}static ssize_t set_fan(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_FAN_MIN: if (ix < 4) { data->fan_min[ix] = FAN_TO_REG(val, 0); } else { /* Refresh the cache */ data->fan_opt[ix] = dme1737_read(client, DME1737_REG_FAN_OPT(ix)); /* Modify the fan min value */ data->fan_min[ix] = FAN_TO_REG(val, FAN_TPC_FROM_REG(data->fan_opt[ix])); } dme1737_write(client, DME1737_REG_FAN_MIN(ix), data->fan_min[ix] & 0xff); dme1737_write(client, DME1737_REG_FAN_MIN(ix) + 1, data->fan_min[ix] >> 8); break; case SYS_FAN_MAX: /* Only valid for fan[5-6] */ data->fan_max[ix - 4] = FAN_MAX_TO_REG(val); dme1737_write(client, DME1737_REG_FAN_MAX(ix), data->fan_max[ix - 4]); break; case SYS_FAN_TYPE: /* Only valid for fan[1-4] */ if (!(val == 1 || val == 2 || val == 4)) { count = -EINVAL; dev_warn(dev, "Fan type value %ld not " "supported. Choose one of 1, 2, or 4.\n", val); goto exit; } data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(client, DME1737_REG_FAN_OPT(ix))); dme1737_write(client, DME1737_REG_FAN_OPT(ix), data->fan_opt[ix]); break; default: dev_dbg(dev, "Unknown function %d.\n", fn); }exit: mutex_unlock(&data->update_lock); return count;}/* --------------------------------------------------------------------- * PWM sysfs attributes * ix = [0-4] * --------------------------------------------------------------------- */#define SYS_PWM 0#define SYS_PWM_FREQ 1#define SYS_PWM_ENABLE 2#define SYS_PWM_RAMP_RATE 3#define SYS_PWM_AUTO_CHANNELS_ZONE 4#define SYS_PWM_AUTO_PWM_MIN 5#define SYS_PWM_AUTO_POINT1_PWM 6#define SYS_PWM_AUTO_POINT2_PWM 7static ssize_t show_pwm(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_PWM: if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 0) { res = 255; } else { res = data->pwm[ix]; } break; case SYS_PWM_FREQ: res = PWM_FREQ_FROM_REG(data->pwm_freq[ix]); break; case SYS_PWM_ENABLE: if (ix > 3) { res = 1; /* pwm[5-6] hard-wired to manual mode */ } else { res = PWM_EN_FROM_REG(data->pwm_config[ix]); } break; case SYS_PWM_RAMP_RATE: /* Only valid for pwm[1-3] */ res = PWM_RR_FROM_REG(data->pwm_rr[ix > 0], ix); break; case SYS_PWM_AUTO_CHANNELS_ZONE: /* Only valid for pwm[1-3] */ if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { res = PWM_ACZ_FROM_REG(data->pwm_config[ix]); } else { res = data->pwm_acz[ix]; } break; case SYS_PWM_AUTO_PWM_MIN: /* Only valid for pwm[1-3] */ if (PWM_OFF_FROM_REG(data->pwm_rr[0], ix)) { res = data->pwm_min[ix]; } else { res = 0; } break; case SYS_PWM_AUTO_POINT1_PWM: /* Only valid for pwm[1-3] */ res = data->pwm_min[ix]; break; case SYS_PWM_AUTO_POINT2_PWM: /* Only valid for pwm[1-3] */ res = 255; /* hard-wired */ break; default: res = 0; dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res);}static struct attribute *dme1737_attr_pwm[];static void dme1737_chmod_file(struct device*, struct attribute*, mode_t);static ssize_t set_pwm(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_PWM: data->pwm[ix] = SENSORS_LIMIT(val, 0, 255); dme1737_write(client, DME1737_REG_PWM(ix), data->pwm[ix]); break; case SYS_PWM_FREQ: data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(client, DME1737_REG_PWM_FREQ(ix))); dme1737_write(client, DME1737_REG_PWM_FREQ(ix), data->pwm_freq[ix]); break; case SYS_PWM_ENABLE: /* Only valid for pwm[1-3] */ if (val < 0 || val > 2) { count = -EINVAL; dev_warn(dev, "PWM enable %ld not " "supported. Choose one of 0, 1, or 2.\n", val); goto exit; } /* Refresh the cache */ data->pwm_config[ix] = dme1737_read(client, DME1737_REG_PWM_CONFIG(ix)); if (val == PWM_EN_FROM_REG(data->pwm_config[ix])) { /* Bail out if no change */ goto exit; } /* Do some housekeeping if we are currently in auto mode */ if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { /* Save the current zone channel assignment */ data->pwm_acz[ix] = PWM_ACZ_FROM_REG( data->pwm_config[ix]); /* Save the current ramp rate state and disable it */ data->pwm_rr[ix > 0] = dme1737_read(client, DME1737_REG_PWM_RR(ix > 0)); data->pwm_rr_en &= ~(1 << ix); if (PWM_RR_EN_FROM_REG(data->pwm_rr[ix > 0], ix)) { data->pwm_rr_en |= (1 << ix); data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(0, ix, data->pwm_rr[ix > 0]); dme1737_write(client, DME1737_REG_PWM_RR(ix > 0), data->pwm_rr[ix > 0]); } } /* Set the new PWM mode */ switch (val) { case 0: /* Change permissions of pwm[ix] to read-only */ dme1737_chmod_file(dev, dme1737_attr_pwm[ix], S_IRUGO); /* Turn fan fully on */ data->pwm_config[ix] = PWM_EN_TO_REG(0, data->pwm_config[ix]); dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); break; case 1: /* Turn on manual mode */ data->pwm_config[ix] = PWM_EN_TO_REG(1, data->pwm_config[ix]); dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); /* Change permissions of pwm[ix] to read-writeable */ dme1737_chmod_file(dev, dme1737_attr_pwm[ix], S_IRUGO | S_IWUSR); break; case 2: /* Change permissions of pwm[ix] to read-only */ dme1737_chmod_file(dev, dme1737_attr_pwm[ix], S_IRUGO); /* Turn on auto mode using the saved zone channel * assignment */ data->pwm_config[ix] = PWM_ACZ_TO_REG( data->pwm_acz[ix], data->pwm_config[ix]); dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); /* Enable PWM ramp rate if previously enabled */ if (data->pwm_rr_en & (1 << ix)) { data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(1, ix, dme1737_read(client, DME1737_REG_PWM_RR(ix > 0))); dme1737_write(client, DME1737_REG_PWM_RR(ix > 0), data->pwm_rr[ix > 0]); } break; } break; case SYS_PWM_RAMP_RATE: /* Only valid for pwm[1-3] */ /* Refresh the cache */ data->pwm_config[ix] = dme1737_read(client, DME1737_REG_PWM_CONFIG(ix)); data->pwm_rr[ix > 0] = dme1737_read(client, DME1737_REG_PWM_RR(ix > 0)); /* Set the ramp rate value */ if (val > 0) { data->pwm_rr[ix > 0] = PWM_RR_TO_REG(val, ix, data->pwm_rr[ix > 0]); } /* Enable/disable the feature only if the associated PWM * output is in automatic mode. */ if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(val > 0, ix, data->pwm_rr[ix > 0]); } dme1737_write(client, DME1737_REG_PWM_RR(ix > 0), data->pwm_rr[ix > 0]); break; case SYS_PWM_AUTO_CHANNELS_ZONE: /* Only valid for pwm[1-3] */ if (!(val == 1 || val == 2 || val == 4 || val == 6 || val == 7)) { count = -EINVAL; dev_warn(dev, "PWM auto channels zone %ld " "not supported. Choose one of 1, 2, 4, 6, " "or 7.\n", val); goto exit; } /* Refresh the cache */ data->pwm_config[ix] = dme1737_read(client, DME1737_REG_PWM_CONFIG(ix)); if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { /* PWM is already in auto mode so update the temp * channel assignment */ data->pwm_config[ix] = PWM_ACZ_TO_REG(val, data->pwm_config[ix]); dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); } else { /* PWM is not in auto mode so we save the temp * channel assignment for later use */ data->pwm_acz[ix] = val; } break; case SYS_PWM_AUTO_PWM_MIN: /* Only valid for pwm[1-3] */ /* Refresh the cache */ data->pwm_min[ix] = dme1737_read(client, DME1737_REG_PWM_MIN(ix)); /* There are only 2 values supported for the auto_pwm_min * value: 0 or auto_point1_pwm. So if the temperature drops * below the auto_point1_temp_hyst value, the fan either turns * off or runs at auto_point1_pwm duty-cycle. */ if (val > ((data->pwm_min[ix] + 1) / 2)) { data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix, dme1737_read(client, DME1737_REG_PWM_RR(0))); } else { data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix, dme1737_read(client, DME1737_REG_PWM_RR(0))); } dme1737_write(client, DME1737_REG_PWM_RR(0), data->pwm_rr[0]); break; case SYS_PWM_AUTO_POINT1_PWM: /* Only valid for pwm[1-3] */ data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255); dme1737_write(client, DME1737_REG_PWM_MIN(ix), data->pwm_min[ix]); break; default: dev_dbg(dev, "Unknown function %d.\n", fn); }exit: mutex_unlock(&data->update_lock); return count;}/* --------------------------------------------------------------------- * Miscellaneous sysfs attributes * --------------------------------------------------------------------- */static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf){ struct i2c_client *client = to_i2c_client(dev); struct dme1737_data *data = i2c_get_clientdata(client); return sprintf(buf, "%d\n", data->vrm);}static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct dme1737_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); data->vrm = val; return count;}static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -