static struct lm87_data *lm87_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct lm87_data *data = i2c_get_clientdata(client); mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { int i, j; dev_dbg(&client->dev, "Updating data.\n"); i = (data->channel & CHAN_TEMP3) ? 1 : 0; j = (data->channel & CHAN_TEMP3) ? 5 : 6; for (; i < j; i++) { data->in[i] = lm87_read_value(client, LM87_REG_IN(i)); data->in_min[i] = lm87_read_value(client, LM87_REG_IN_MIN(i)); data->in_max[i] = lm87_read_value(client, LM87_REG_IN_MAX(i)); } for (i = 0; i < 2; i++) { if (data->channel & CHAN_NO_FAN(i)) { data->in[6+i] = lm87_read_value(client, LM87_REG_AIN(i)); data->in_max[6+i] = lm87_read_value(client, LM87_REG_AIN_MAX(i)); data->in_min[6+i] = lm87_read_value(client, LM87_REG_AIN_MIN(i)); } else { data->fan[i] = lm87_read_value(client, LM87_REG_FAN(i)); data->fan_min[i] = lm87_read_value(client, LM87_REG_FAN_MIN(i)); } } j = (data->channel & CHAN_TEMP3) ? 3 : 2; for (i = 0 ; i < j; i++) { data->temp[i] = lm87_read_value(client, LM87_REG_TEMP[i]); data->temp_high[i] = lm87_read_value(client, LM87_REG_TEMP_HIGH[i]); data->temp_low[i] = lm87_read_value(client, LM87_REG_TEMP_LOW[i]); } i = lm87_read_value(client, LM87_REG_TEMP_HW_INT_LOCK); j = lm87_read_value(client, LM87_REG_TEMP_HW_INT); data->temp_crit_int = min(i, j); i = lm87_read_value(client, LM87_REG_TEMP_HW_EXT_LOCK); j = lm87_read_value(client, LM87_REG_TEMP_HW_EXT); data->temp_crit_ext = min(i, j); i = lm87_read_value(client, LM87_REG_VID_FAN_DIV); data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[1] = (i >> 6) & 0x03; data->vid = (i & 0x0F) | (lm87_read_value(client, LM87_REG_VID4) & 0x01) << 4; data->alarms = lm87_read_value(client, LM87_REG_ALARMS1) | (lm87_read_value(client, LM87_REG_ALARMS2) << 8); data->aout = lm87_read_value(client, LM87_REG_AOUT); data->last_updated = jiffies; data->valid = 1; }
int efx_lm87_probe(struct i2c_client *new_client, const struct i2c_device_id *id) #endif { struct lm87_data *data; int err; data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } i2c_set_clientdata(new_client, data); data->valid = 0; mutex_init(&data->update_lock); /* Initialize the LM87 chip */ lm87_init_client(new_client); data->in_scale[0] = 2500; data->in_scale[1] = 2700; data->in_scale[2] = (data->channel & CHAN_VCC_5V) ? 5000 : 3300; data->in_scale[3] = 5000; data->in_scale[4] = 12000; data->in_scale[5] = 2700; data->in_scale[6] = 1875; data->in_scale[7] = 1875; /* Register sysfs hooks */ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group))) goto exit_free; if (data->channel & CHAN_NO_FAN(0)) { if ((err = device_create_file(&new_client->dev, &dev_attr_in6_input)) || (err = device_create_file(&new_client->dev, &dev_attr_in6_min)) || (err = device_create_file(&new_client->dev, &dev_attr_in6_max)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_in6_alarm.dev_attr))) goto exit_remove; } else { if ((err = device_create_file(&new_client->dev, &dev_attr_fan1_input)) || (err = device_create_file(&new_client->dev, &dev_attr_fan1_min)) || (err = device_create_file(&new_client->dev, &dev_attr_fan1_div)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_fan1_alarm.dev_attr))) goto exit_remove; } if (data->channel & CHAN_NO_FAN(1)) { if ((err = device_create_file(&new_client->dev, &dev_attr_in7_input)) || (err = device_create_file(&new_client->dev, &dev_attr_in7_min)) || (err = device_create_file(&new_client->dev, &dev_attr_in7_max)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_in7_alarm.dev_attr))) goto exit_remove; } else { if ((err = device_create_file(&new_client->dev, &dev_attr_fan2_input)) || (err = device_create_file(&new_client->dev, &dev_attr_fan2_min)) || (err = device_create_file(&new_client->dev, &dev_attr_fan2_div)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_fan2_alarm.dev_attr))) goto exit_remove; } if (data->channel & CHAN_TEMP3) { if ((err = device_create_file(&new_client->dev, &dev_attr_temp3_input)) || (err = device_create_file(&new_client->dev, &dev_attr_temp3_max)) || (err = device_create_file(&new_client->dev, &dev_attr_temp3_min)) || (err = device_create_file(&new_client->dev, &dev_attr_temp3_crit)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_temp3_alarm.dev_attr)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_temp3_fault.dev_attr))) goto exit_remove; } else { if ((err = device_create_file(&new_client->dev, &dev_attr_in0_input)) || (err = device_create_file(&new_client->dev, &dev_attr_in0_min)) || (err = device_create_file(&new_client->dev, &dev_attr_in0_max)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_in0_alarm.dev_attr)) || (err = device_create_file(&new_client->dev, &dev_attr_in5_input)) || (err = device_create_file(&new_client->dev, &dev_attr_in5_min)) || (err = device_create_file(&new_client->dev, &dev_attr_in5_max)) || (err = device_create_file(&new_client->dev, &sensor_dev_attr_in5_alarm.dev_attr))) goto exit_remove; } if (!(data->channel & CHAN_NO_VID)) { data->vrm = vid_which_vrm(); if ((err = device_create_file(&new_client->dev, &dev_attr_cpu0_vid)) || (err = device_create_file(&new_client->dev, &dev_attr_vrm))) goto exit_remove; } data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); goto exit_remove; } return 0; exit_remove: sysfs_remove_group(&new_client->dev.kobj, &lm87_group); sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt); exit_free: lm87_write_value(new_client, LM87_REG_CONFIG, data->config); kfree(data); exit: return err; }