void sis5595_fan(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { struct sis5595_data *data = client->data; int nr = ctl_name - SIS5595_SYSCTL_FAN1 + 1; if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; else if (operation == SENSORS_PROC_REAL_READ) { sis5595_update_client(client); results[0] = FAN_FROM_REG(data->fan_min[nr - 1], DIV_FROM_REG(data->fan_div[nr - 1])); results[1] = FAN_FROM_REG(data->fan[nr - 1], DIV_FROM_REG(data->fan_div[nr - 1])); *nrels_mag = 2; } else if (operation == SENSORS_PROC_REAL_WRITE) { if (*nrels_mag >= 1) { data->fan_min[nr - 1] = FAN_TO_REG(results[0], DIV_FROM_REG (data-> fan_div[nr-1])); sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr - 1]); } } }
static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct gl520_data *data = i2c_get_clientdata(client); int n = to_sensor_dev_attr(attr)->index; unsigned long v = simple_strtoul(buf, NULL, 10); u8 r; mutex_lock(&data->update_lock); r = FAN_TO_REG(v, data->fan_div[n]); data->fan_min[n] = r; if (n == 0) gl520_write_value(client, GL520_REG_FAN_MIN, (gl520_read_value(client, GL520_REG_FAN_MIN) & ~0xff00) | (r << 8)); else gl520_write_value(client, GL520_REG_FAN_MIN, (gl520_read_value(client, GL520_REG_FAN_MIN) & ~0xff) | r); data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); if (data->fan_min[n] == 0) data->alarm_mask &= (n == 0) ? ~0x20 : ~0x40; else data->alarm_mask |= (n == 0) ? 0x20 : 0x40; data->beep_mask &= data->alarm_mask; gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); mutex_unlock(&data->update_lock); return count; }
void maxi99_fan(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { struct maxi_data *data = client->data; int nr; nr = ctl_name - MAXI_SYSCTL_FAN1 + 1; if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; else if (operation == SENSORS_PROC_REAL_READ) { maxi99_update_client(client, fan, nr - 1); results[0] = FAN99_FROM_REG(data->fan_min[nr - 1]); /* min rpm */ results[1] = data->fan_div[nr - 1]; /* divisor */ results[2] = FAN99_FROM_REG(data->fan[nr - 1]); /* rpm */ *nrels_mag = 3; } else if (operation == SENSORS_PROC_REAL_WRITE) { #ifndef NOWRITE /* still to do */ if (*nrels_mag >= 1) { data->fan_min[nr - 1] = FAN_TO_REG(results[0]); maxi_write_value(client, MAXI_REG_FAN_MIN(nr), data->fan_min[nr - 1]); } #endif } }
/* The next few functions are the call-back functions of the /proc/sys and sysctl files. Which function is used is defined in the ctl_table in the extra1 field. Each function must return the magnitude (power of 10 to divide the data with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must put a maximum of *nrels elements in results reflecting the data of this file, and set *nrels to the number it actually put in it, if operation== SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE. Note that on SENSORS_PROC_REAL_READ, I do not check whether results is large enough (by checking the incoming value of *nrels). This is not very good practice, but as long as you put less than about 5 values in results, you can assume it is large enough. */ void maxi_fan(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { struct maxi_data *data = client->data; int nr; if (data->type == nba) { maxi99_fan(client, operation, ctl_name, nrels_mag, results); return; } nr = ctl_name - MAXI_SYSCTL_FAN1 + 1; if (operation == SENSORS_PROC_REAL_INFO) *nrels_mag = 0; else if (operation == SENSORS_PROC_REAL_READ) { maxi_update_client(client); results[0] = FAN_FROM_REG(data->fan_min[nr - 1]); results[1] = data->fan_div[nr - 1]; results[2] = FAN_FROM_REG(data->fan[nr - 1]); *nrels_mag = 3; } else if (operation == SENSORS_PROC_REAL_WRITE) { #ifndef NOWRITE if (*nrels_mag >= 1) { data->fan_min[nr - 1] = FAN_TO_REG(results[0]); maxi_write_value(client, MAXI_REG_FAN_MIN(nr), data->fan_min[nr - 1]); } #endif } }
/* Called when we have found a new SIS5595. It should set limits, etc. */ void sis5595_init_client(struct i2c_client *client) { struct sis5595_data *data = client->data; /* Reset all except Watchdog values and last conversion values This sets fan-divs to 2, among others */ sis5595_write_value(client, SIS5595_REG_CONFIG, 0x80); sis5595_write_value(client, SIS5595_REG_IN_MIN(0), IN_TO_REG(SIS5595_INIT_IN_MIN_0)); sis5595_write_value(client, SIS5595_REG_IN_MAX(0), IN_TO_REG(SIS5595_INIT_IN_MAX_0)); sis5595_write_value(client, SIS5595_REG_IN_MIN(1), IN_TO_REG(SIS5595_INIT_IN_MIN_1)); sis5595_write_value(client, SIS5595_REG_IN_MAX(1), IN_TO_REG(SIS5595_INIT_IN_MAX_1)); sis5595_write_value(client, SIS5595_REG_IN_MIN(2), IN_TO_REG(SIS5595_INIT_IN_MIN_2)); sis5595_write_value(client, SIS5595_REG_IN_MAX(2), IN_TO_REG(SIS5595_INIT_IN_MAX_2)); sis5595_write_value(client, SIS5595_REG_IN_MIN(3), IN_TO_REG(SIS5595_INIT_IN_MIN_3)); sis5595_write_value(client, SIS5595_REG_IN_MAX(3), IN_TO_REG(SIS5595_INIT_IN_MAX_3)); sis5595_write_value(client, SIS5595_REG_FAN_MIN(1), FAN_TO_REG(SIS5595_INIT_FAN_MIN_1, 2)); sis5595_write_value(client, SIS5595_REG_FAN_MIN(2), FAN_TO_REG(SIS5595_INIT_FAN_MIN_2, 2)); if(data->maxins == 4) { sis5595_write_value(client, SIS5595_REG_IN_MIN(4), IN_TO_REG(SIS5595_INIT_IN_MIN_4)); sis5595_write_value(client, SIS5595_REG_IN_MAX(4), IN_TO_REG(SIS5595_INIT_IN_MAX_4)); } else { sis5595_write_value(client, SIS5595_REG_TEMP_OVER, TEMP_TO_REG(SIS5595_INIT_TEMP_OVER)); sis5595_write_value(client, SIS5595_REG_TEMP_HYST, TEMP_TO_REG(SIS5595_INIT_TEMP_HYST)); } /* Start monitoring */ sis5595_write_value(client, SIS5595_REG_CONFIG, (sis5595_read_value(client, SIS5595_REG_CONFIG) & 0xf7) | 0x01); }
/* Called when we have found a new GL520SM. It should set limits, etc. */ void gl520_init_client(struct i2c_client *client) { /* Power-on defaults (bit 7=1) */ gl520_write_value(client, GL520_REG_CONF, 0x80); /* No noisy output (bit 2=1), Comparator mode (bit 3=0), two fans (bit4=0), standby mode (bit6=0) */ gl520_write_value(client, GL520_REG_CONF, 0x04); /* Never interrupts */ gl520_write_value(client, GL520_REG_MASK, 0x00); gl520_write_value(client, GL520_REG_TEMP1_HYST, TEMP_TO_REG(GL520_INIT_TEMP_HYST)); gl520_write_value(client, GL520_REG_TEMP1_OVER, TEMP_TO_REG(GL520_INIT_TEMP_OVER)); /* We set Temp2, but not Vin4. */ gl520_write_value(client, GL520_REG_TEMP2_HYST, TEMP_TO_REG(GL520_INIT_TEMP_HYST)); gl520_write_value(client, GL520_REG_TEMP2_OVER, TEMP_TO_REG(GL520_INIT_TEMP_OVER)); gl520_write_value(client, GL520_REG_MISC, (DIV_TO_REG(2) << 6) | (DIV_TO_REG(2) << 4)); gl520_write_value(client, GL520_REG_FAN_LIMIT, (FAN_TO_REG(GL520_INIT_FAN_MIN_1, 2) << 8) | FAN_TO_REG(GL520_INIT_FAN_MIN_2, 2)); gl520_write_value(client, GL520_REG_VIN1_LIMIT, (IN_TO_REG(GL520_INIT_VIN_MAX_1) << 8) | IN_TO_REG(GL520_INIT_VIN_MIN_1)); gl520_write_value(client, GL520_REG_VIN2_LIMIT, (IN_TO_REG(GL520_INIT_VIN_MAX_2) << 8) | IN_TO_REG(GL520_INIT_VIN_MIN_2)); gl520_write_value(client, GL520_REG_VIN3_LIMIT, (IN_TO_REG(GL520_INIT_VIN_MAX_3) << 8) | IN_TO_REG(GL520_INIT_VIN_MIN_3)); gl520_write_value(client, GL520_REG_VDD_LIMIT, (VDD_TO_REG(GL520_INIT_VDD_MAX) << 8) | VDD_TO_REG(GL520_INIT_VDD_MIN)); /* Clear status register (bit 5=1), start (bit6=1) */ gl520_write_value(client, GL520_REG_CONF, 0x24); gl520_write_value(client, GL520_REG_CONF, 0x44); }
/* * Note: we save and restore the fan minimum here, because its value is * determined in part by the fan divisor. This follows the principle of * least surprise; the user doesn't expect the fan minimum to change just * because the divisor changed. */ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm78_data *data = dev_get_drvdata(dev); int nr = attr->index; unsigned long min; u8 reg; unsigned long val; int err; err = kstrtoul(buf, 10, &val); if (err) return err; mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); switch (val) { case 1: data->fan_div[nr] = 0; break; case 2: data->fan_div[nr] = 1; break; case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: dev_err(dev, "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", val); mutex_unlock(&data->update_lock); return -EINVAL; } reg = lm78_read_value(data, LM78_REG_VID_FANDIV); switch (nr) { case 0: reg = (reg & 0xcf) | (data->fan_div[nr] << 4); break; case 1: reg = (reg & 0x3f) | (data->fan_div[nr] << 6); break; } lm78_write_value(data, LM78_REG_VID_FANDIV, reg); data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; }
static void set_fan_min(struct device *dev, const char *buf, int nr) { struct i2c_client *client = to_i2c_client(dev); struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); }
static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm78_data *data = dev_get_drvdata(dev); int nr = attr->index; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; }
static ssize_t set_fan(struct device *dev, struct device_attribute *dummy, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct lm63_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan[1] = FAN_TO_REG(val); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, data->fan[1] & 0xFF); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, data->fan[1] >> 8); mutex_unlock(&data->update_lock); return count; }
/* Note: we save and restore the fan minimum here, because its value is determined in part by the fan clock divider. This follows the principle of least surprise; the user doesn't expect the fan minimum to change just because the divider changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct lm87_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); unsigned long min; u8 reg; mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], FAN_DIV_FROM_REG(data->fan_div[nr])); switch (val) { case 1: data->fan_div[nr] = 0; break; case 2: data->fan_div[nr] = 1; break; case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: mutex_unlock(&data->update_lock); return -EINVAL; } reg = lm87_read_value(client, LM87_REG_VID_FAN_DIV); switch (nr) { case 0: reg = (reg & 0xCF) | (data->fan_div[0] << 4); break; case 1: reg = (reg & 0x3F) | (data->fan_div[1] << 6); break; } lm87_write_value(client, LM87_REG_VID_FAN_DIV, reg); data->fan_min[nr] = FAN_TO_REG(min, val); lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; }
static ssize_t set_fan(struct device *dev, struct device_attribute *dummy, const char *buf, size_t count) { struct lm63_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; unsigned long val; int err; err = kstrtoul(buf, 10, &val); if (err) return err; mutex_lock(&data->update_lock); data->fan[1] = FAN_TO_REG(val); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, data->fan[1] & 0xFF); i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, data->fan[1] >> 8); mutex_unlock(&data->update_lock); return count; }
/* Called when we have found a new MTP008. It should set limits, etc. */ void mtp008_init_client(struct i2c_client *client) { int vid; u8 save1, save2; struct mtp008_data *data; data = client->data; /* * Initialize the Myson MTP008 hardware monitoring chip. * Save the pin settings that the BIOS hopefully set. */ save1 = mtp008_read_value(client, MTP008_REG_PIN_CTRL1); save2 = mtp008_read_value(client, MTP008_REG_PIN_CTRL2); mtp008_write_value(client, MTP008_REG_CONFIG, (mtp008_read_value(client, MTP008_REG_CONFIG) & 0x7f) | 0x80); mtp008_write_value(client, MTP008_REG_PIN_CTRL1, save1); mtp008_write_value(client, MTP008_REG_PIN_CTRL2, save2); mtp008_getsensortype(data, save2); /* * Retrieve the VID setting (needed for the default limits). */ vid = mtp008_read_value(client, MTP008_REG_VID_FANDIV) & 0x0f; vid |= (mtp008_read_value(client, MTP008_REG_RESET_VID4) & 0x01) << 4; vid = VID_FROM_REG(vid); /* * Set the default limits. * * Setting temp sensors is done as follows: * * Register 0x57: 0 0 0 0 x x x x * | \ / +-- AIN5/VT3 * | +----- AIN4/VT2/PII * +-------- VT1/PII */ mtp008_write_value(client, MTP008_REG_IN_MAX(0), IN_TO_REG(MTP008_INIT_IN_MAX_0)); mtp008_write_value(client, MTP008_REG_IN_MIN(0), IN_TO_REG(MTP008_INIT_IN_MIN_0)); mtp008_write_value(client, MTP008_REG_IN_MAX(1), IN_TO_REG(MTP008_INIT_IN_MAX_1)); mtp008_write_value(client, MTP008_REG_IN_MIN(1), IN_TO_REG(MTP008_INIT_IN_MIN_1)); mtp008_write_value(client, MTP008_REG_IN_MAX(2), IN_TO_REG(MTP008_INIT_IN_MAX_2)); mtp008_write_value(client, MTP008_REG_IN_MIN(2), IN_TO_REG(MTP008_INIT_IN_MIN_2)); mtp008_write_value(client, MTP008_REG_IN_MAX(3), IN_TO_REG(MTP008_INIT_IN_MAX_3)); mtp008_write_value(client, MTP008_REG_IN_MIN(3), IN_TO_REG(MTP008_INIT_IN_MIN_3)); mtp008_write_value(client, MTP008_REG_IN_MAX(5), IN_TO_REG(MTP008_INIT_IN_MAX_5)); mtp008_write_value(client, MTP008_REG_IN_MIN(5), IN_TO_REG(MTP008_INIT_IN_MIN_5)); mtp008_write_value(client, MTP008_REG_IN_MAX(6), IN_TO_REG(MTP008_INIT_IN_MAX_6)); mtp008_write_value(client, MTP008_REG_IN_MIN(6), IN_TO_REG(MTP008_INIT_IN_MIN_6)); mtp008_write_value(client, MTP008_REG_TEMP_MAX, TEMP_TO_REG(MTP008_INIT_TEMP_OVER)); mtp008_write_value(client, MTP008_REG_TEMP_MIN, TEMP_TO_REG(MTP008_INIT_TEMP_HYST)); mtp008_write_value(client, MTP008_REG_IN_MAX(4), TEMP_TO_REG(MTP008_INIT_TEMP2_OVER)); mtp008_write_value(client, MTP008_REG_IN_MIN(4), TEMP_TO_REG(MTP008_INIT_TEMP2_HYST)); mtp008_write_value(client, MTP008_REG_FAN_MIN(1), FAN_TO_REG(MTP008_INIT_FAN_MIN_1, 2)); mtp008_write_value(client, MTP008_REG_FAN_MIN(2), FAN_TO_REG(MTP008_INIT_FAN_MIN_2, 2)); mtp008_write_value(client, MTP008_REG_FAN_MIN(3), FAN_TO_REG(MTP008_INIT_FAN_MIN_3, 2)); /* * Start monitoring. */ mtp008_write_value( client, MTP008_REG_CONFIG, (mtp008_read_value(client, MTP008_REG_CONFIG) & 0xf7) | 0x01 ); }