lm93.c
来自「linux 内核源代码」· C语言 代码 · 共 2,063 行 · 第 1/5 页
C
2,063 行
/* <TODO> how to handle write errors? */ result = i2c_smbus_write_word_data(client, reg, value); if (result < 0) dev_warn(&client->dev,"lm93: write word data failed, " "0x%04x at address 0x%02x.\n", value, reg); return result;}static u8 lm93_block_buffer[I2C_SMBUS_BLOCK_MAX];/* read block data into values, retry if not expected length fbn => index to lm93_block_read_cmds table (Fixed Block Number - section 14.5.2 of LM93 datasheet)*/static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values){ int i, result=0; for (i = 1; i <= MAX_RETRIES; i++) { result = i2c_smbus_read_block_data(client, lm93_block_read_cmds[fbn].cmd, lm93_block_buffer); if (result == lm93_block_read_cmds[fbn].len) { break; } else { dev_warn(&client->dev,"lm93: block read data failed, " "command 0x%02x.\n", lm93_block_read_cmds[fbn].cmd); mdelay(i + 3); } } if (result == lm93_block_read_cmds[fbn].len) { memcpy(values,lm93_block_buffer,lm93_block_read_cmds[fbn].len); } else { /* <TODO> what to do in case of error? */ }}static struct lm93_data *lm93_update_device(struct device *dev){ struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); const unsigned long interval = HZ + (HZ / 2); mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + interval) || !data->valid) { data->update(data, client); data->last_updated = jiffies; data->valid = 1; } mutex_unlock(&data->update_lock); return data;}/* update routine for data that has no corresponding SMBus block command */static void lm93_update_client_common(struct lm93_data *data, struct i2c_client *client){ int i; u8 *ptr; /* temp1 - temp4: limits */ for (i = 0; i < 4; i++) { data->temp_lim[i].min = lm93_read_byte(client, LM93_REG_TEMP_MIN(i)); data->temp_lim[i].max = lm93_read_byte(client, LM93_REG_TEMP_MAX(i)); } /* config register */ data->config = lm93_read_byte(client, LM93_REG_CONFIG); /* vid1 - vid2: values */ for (i = 0; i < 2; i++) data->vid[i] = lm93_read_byte(client, LM93_REG_VID(i)); /* prochot1 - prochot2: limits */ for (i = 0; i < 2; i++) data->prochot_max[i] = lm93_read_byte(client, LM93_REG_PROCHOT_MAX(i)); /* vccp1 - vccp2: VID relative limits */ for (i = 0; i < 2; i++) data->vccp_limits[i] = lm93_read_byte(client, LM93_REG_VCCP_LIMIT_OFF(i)); /* GPIO input state */ data->gpi = lm93_read_byte(client, LM93_REG_GPI); /* #PROCHOT override state */ data->prochot_override = lm93_read_byte(client, LM93_REG_PROCHOT_OVERRIDE); /* #PROCHOT intervals */ data->prochot_interval = lm93_read_byte(client, LM93_REG_PROCHOT_INTERVAL); /* Fan Boost Termperature registers */ for (i = 0; i < 4; i++) data->boost[i] = lm93_read_byte(client, LM93_REG_BOOST(i)); /* Fan Boost Temperature Hyst. registers */ data->boost_hyst[0] = lm93_read_byte(client, LM93_REG_BOOST_HYST_12); data->boost_hyst[1] = lm93_read_byte(client, LM93_REG_BOOST_HYST_34); /* Temperature Zone Min. PWM & Hysteresis registers */ data->auto_pwm_min_hyst[0] = lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_12); data->auto_pwm_min_hyst[1] = lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_34); /* #PROCHOT & #VRDHOT PWM Ramp Control register */ data->pwm_ramp_ctl = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL); /* misc setup registers */ data->sfc1 = lm93_read_byte(client, LM93_REG_SFC1); data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); data->sf_tach_to_pwm = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM); /* write back alarm values to clear */ for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++) lm93_write_byte(client, LM93_REG_HOST_ERROR_1 + i, *(ptr + i));}/* update routine which uses SMBus block data commands */static void lm93_update_client_full(struct lm93_data *data, struct i2c_client *client){ dev_dbg(&client->dev,"starting device update (block data enabled)\n"); /* in1 - in16: values & limits */ lm93_read_block(client, 3, (u8 *)(data->block3)); lm93_read_block(client, 7, (u8 *)(data->block7)); /* temp1 - temp4: values */ lm93_read_block(client, 2, (u8 *)(data->block2)); /* prochot1 - prochot2: values */ lm93_read_block(client, 4, (u8 *)(data->block4)); /* fan1 - fan4: values & limits */ lm93_read_block(client, 5, (u8 *)(data->block5)); lm93_read_block(client, 8, (u8 *)(data->block8)); /* pmw control registers */ lm93_read_block(client, 9, (u8 *)(data->block9)); /* alarm values */ lm93_read_block(client, 1, (u8 *)(&data->block1)); /* auto/pwm registers */ lm93_read_block(client, 10, (u8 *)(&data->block10)); lm93_update_client_common(data, client);}/* update routine which uses SMBus byte/word data commands only */static void lm93_update_client_min(struct lm93_data *data, struct i2c_client *client){ int i,j; u8 *ptr; dev_dbg(&client->dev,"starting device update (block data disabled)\n"); /* in1 - in16: values & limits */ for (i = 0; i < 16; i++) { data->block3[i] = lm93_read_byte(client, LM93_REG_IN(i)); data->block7[i].min = lm93_read_byte(client, LM93_REG_IN_MIN(i)); data->block7[i].max = lm93_read_byte(client, LM93_REG_IN_MAX(i)); } /* temp1 - temp4: values */ for (i = 0; i < 4; i++) { data->block2[i] = lm93_read_byte(client, LM93_REG_TEMP(i)); } /* prochot1 - prochot2: values */ for (i = 0; i < 2; i++) { data->block4[i].cur = lm93_read_byte(client, LM93_REG_PROCHOT_CUR(i)); data->block4[i].avg = lm93_read_byte(client, LM93_REG_PROCHOT_AVG(i)); } /* fan1 - fan4: values & limits */ for (i = 0; i < 4; i++) { data->block5[i] = lm93_read_word(client, LM93_REG_FAN(i)); data->block8[i] = lm93_read_word(client, LM93_REG_FAN_MIN(i)); } /* pwm control registers */ for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { data->block9[i][j] = lm93_read_byte(client, LM93_REG_PWM_CTL(i,j)); } } /* alarm values */ for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++) { *(ptr + i) = lm93_read_byte(client, LM93_REG_HOST_ERROR_1 + i); } /* auto/pwm (base temp) registers */ for (i = 0; i < 4; i++) { data->block10.base[i] = lm93_read_byte(client, LM93_REG_TEMP_BASE(i)); } /* auto/pwm (offset temp) registers */ for (i = 0; i < 12; i++) { data->block10.offset[i] = lm93_read_byte(client, LM93_REG_TEMP_OFFSET(i)); } lm93_update_client_common(data, client);}/* following are the sysfs callback functions */static ssize_t show_in(struct device *dev, struct device_attribute *attr, char *buf){ int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); return sprintf(buf, "%d\n", LM93_IN_FROM_REG(nr, data->block3[nr]));}static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 0);static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 1);static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 2);static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 3);static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 4);static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 5);static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 6);static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 7);static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in, NULL, 8);static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in, NULL, 9);static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_in, NULL, 10);static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_in, NULL, 11);static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_in, NULL, 12);static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_in, NULL, 13);static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_in, NULL, 14);static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in, NULL, 15);static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, char *buf){ int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); int vccp = nr - 6; long rc, vid; if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) { vid = LM93_VID_FROM_REG(data->vid[vccp]); rc = LM93_IN_MIN_FROM_REG(data->vccp_limits[vccp], vid); } else { rc = LM93_IN_FROM_REG(nr, data->block7[nr].min); \ } return sprintf(buf, "%ld\n", rc); \}static ssize_t store_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ int nr = (to_sensor_dev_attr(attr))->index; struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); u32 val = simple_strtoul(buf, NULL, 10); int vccp = nr - 6; long vid; mutex_lock(&data->update_lock); if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) { vid = LM93_VID_FROM_REG(data->vid[vccp]); data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0xf0) | LM93_IN_REL_TO_REG(val, 0, vid); lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp), data->vccp_limits[vccp]); } else { data->block7[nr].min = LM93_IN_TO_REG(nr,val); lm93_write_byte(client, LM93_REG_IN_MIN(nr), data->block7[nr].min); } mutex_unlock(&data->update_lock); return count;}static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0);static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1);static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2);static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3);static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4);static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5);static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6);static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7);static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8);static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9);static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 10);static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 11);static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 12);static SENSOR_DEVICE_ATTR(in14_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 13);static SENSOR_DEVICE_ATTR(in15_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 14);static SENSOR_DEVICE_ATTR(in16_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 15);static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, char *buf){ int nr = (to_sensor_dev_attr(attr))->index; struct lm93_data *data = lm93_update_device(dev); int vccp = nr - 6; long rc, vid; if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) { vid = LM93_VID_FROM_REG(data->vid[vccp]); rc = LM93_IN_MAX_FROM_REG(data->vccp_limits[vccp],vid); } else { rc = LM93_IN_FROM_REG(nr,data->block7[nr].max); \ } return sprintf(buf,"%ld\n",rc); \}static ssize_t store_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ int nr = (to_sensor_dev_attr(attr))->index; struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); u32 val = simple_strtoul(buf, NULL, 10); int vccp = nr - 6; long vid; mutex_lock(&data->update_lock); if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) { vid = LM93_VID_FROM_REG(data->vid[vccp]); data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0x0f) | LM93_IN_REL_TO_REG(val, 1, vid); lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp), data->vccp_limits[vccp]); } else { data->block7[nr].max = LM93_IN_TO_REG(nr,val); lm93_write_byte(client, LM93_REG_IN_MAX(nr), data->block7[nr].max); } mutex_unlock(&data->update_lock); return count;}static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0);static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1);static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2);static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3);static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4);static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5);static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6);static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7);static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8);static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9);static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 10);static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 11);static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 12);static SENSOR_DEVICE_ATTR(in14_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 13);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?