📄 adm1026.c
字号:
}void adm1026_init_client(struct i2c_client *client){ int value, i; struct adm1026_data *data = i2c_get_clientdata(client); dev_dbg(&client->dev,"(%d): Initializing device\n", client->id); /* Read chip config */ data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); /* Inform user of chip config */ dev_dbg(&client->dev, "(%d): ADM1026_REG_CONFIG1 is: 0x%02x\n", client->id, data->config1); if ((data->config1 & CFG1_MONITOR) == 0) { dev_dbg(&client->dev, "(%d): Monitoring not currently " "enabled.\n", client->id); } if (data->config1 & CFG1_INT_ENABLE) { dev_dbg(&client->dev, "(%d): SMBALERT interrupts are " "enabled.\n", client->id); } if (data->config1 & CFG1_AIN8_9) { dev_dbg(&client->dev, "(%d): in8 and in9 enabled. " "temp3 disabled.\n", client->id); } else { dev_dbg(&client->dev, "(%d): temp3 enabled. in8 and " "in9 disabled.\n", client->id); } if (data->config1 & CFG1_THERM_HOT) { dev_dbg(&client->dev, "(%d): Automatic THERM, PWM, " "and temp limits enabled.\n", client->id); } value = data->config3; if (data->config3 & CFG3_GPIO16_ENABLE) { dev_dbg(&client->dev, "(%d): GPIO16 enabled. THERM" "pin disabled.\n", client->id); } else { dev_dbg(&client->dev, "(%d): THERM pin enabled. " "GPIO16 disabled.\n", client->id); } if (data->config3 & CFG3_VREF_250) { dev_dbg(&client->dev, "(%d): Vref is 2.50 Volts.\n", client->id); } else { dev_dbg(&client->dev, "(%d): Vref is 1.82 Volts.\n", client->id); } /* Read and pick apart the existing GPIO configuration */ value = 0; for (i = 0;i <= 15;++i) { if ((i & 0x03) == 0) { value = adm1026_read_value(client, ADM1026_REG_GPIO_CFG_0_3 + i/4); } data->gpio_config[i] = value & 0x03; value >>= 2; } data->gpio_config[16] = (data->config3 >> 6) & 0x03; /* ... and then print it */ adm1026_print_gpio(client); /* If the user asks us to reprogram the GPIO config, then * do it now. But only if this is the first ADM1026. */ if (client->id == 0 && (gpio_input[0] != -1 || gpio_output[0] != -1 || gpio_inverted[0] != -1 || gpio_normal[0] != -1 || gpio_fan[0] != -1)) { adm1026_fixup_gpio(client); } /* WE INTENTIONALLY make no changes to the limits, * offsets, pwms, fans and zones. If they were * configured, we don't want to mess with them. * If they weren't, the default is 100% PWM, no * control and will suffice until 'sensors -s' * can be run by the user. We DO set the default * value for pwm1.auto_pwm_min to its maximum * so that enabling automatic pwm fan control * without first setting a value for pwm1.auto_pwm_min * will not result in potentially dangerous fan speed decrease. */ data->pwm1.auto_pwm_min=255; /* Start monitoring */ value = adm1026_read_value(client, ADM1026_REG_CONFIG1); /* Set MONITOR, clear interrupt acknowledge and s/w reset */ value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); dev_dbg(&client->dev, "(%d): Setting CONFIG to: 0x%02x\n", client->id, value); data->config1 = value; adm1026_write_value(client, ADM1026_REG_CONFIG1, value); /* initialize fan_div[] to hardware defaults */ value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); for (i = 0;i <= 7;++i) { data->fan_div[i] = DIV_FROM_REG(value & 0x03); value >>= 2; }}void adm1026_print_gpio(struct i2c_client *client){ struct adm1026_data *data = i2c_get_clientdata(client); int i; dev_dbg(&client->dev, "(%d): GPIO config is:", client->id); for (i = 0;i <= 7;++i) { if (data->config2 & (1 << i)) { dev_dbg(&client->dev, "\t(%d): %sGP%s%d\n", client->id, data->gpio_config[i] & 0x02 ? "" : "!", data->gpio_config[i] & 0x01 ? "OUT" : "IN", i); } else { dev_dbg(&client->dev, "\t(%d): FAN%d\n", client->id, i); } } for (i = 8;i <= 15;++i) { dev_dbg(&client->dev, "\t(%d): %sGP%s%d\n", client->id, data->gpio_config[i] & 0x02 ? "" : "!", data->gpio_config[i] & 0x01 ? "OUT" : "IN", i); } if (data->config3 & CFG3_GPIO16_ENABLE) { dev_dbg(&client->dev, "\t(%d): %sGP%s16\n", client->id, data->gpio_config[16] & 0x02 ? "" : "!", data->gpio_config[16] & 0x01 ? "OUT" : "IN"); } else { /* GPIO16 is THERM */ dev_dbg(&client->dev, "\t(%d): THERM\n", client->id); }}void adm1026_fixup_gpio(struct i2c_client *client){ struct adm1026_data *data = i2c_get_clientdata(client); int i; int value; /* Make the changes requested. */ /* We may need to unlock/stop monitoring or soft-reset the * chip before we can make changes. This hasn't been * tested much. FIXME */ /* Make outputs */ for (i = 0;i <= 16;++i) { if (gpio_output[i] >= 0 && gpio_output[i] <= 16) { data->gpio_config[gpio_output[i]] |= 0x01; } /* if GPIO0-7 is output, it isn't a FAN tach */ if (gpio_output[i] >= 0 && gpio_output[i] <= 7) { data->config2 |= 1 << gpio_output[i]; } } /* Input overrides output */ for (i = 0;i <= 16;++i) { if (gpio_input[i] >= 0 && gpio_input[i] <= 16) { data->gpio_config[gpio_input[i]] &= ~ 0x01; } /* if GPIO0-7 is input, it isn't a FAN tach */ if (gpio_input[i] >= 0 && gpio_input[i] <= 7) { data->config2 |= 1 << gpio_input[i]; } } /* Inverted */ for (i = 0;i <= 16;++i) { if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) { data->gpio_config[gpio_inverted[i]] &= ~ 0x02; } } /* Normal overrides inverted */ for (i = 0;i <= 16;++i) { if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) { data->gpio_config[gpio_normal[i]] |= 0x02; } } /* Fan overrides input and output */ for (i = 0;i <= 7;++i) { if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) { data->config2 &= ~(1 << gpio_fan[i]); } } /* Write new configs to registers */ adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); data->config3 = (data->config3 & 0x3f) | ((data->gpio_config[16] & 0x03) << 6); adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); for (i = 15, value = 0;i >= 0;--i) { value <<= 2; value |= data->gpio_config[i] & 0x03; if ((i & 0x03) == 0) { adm1026_write_value(client, ADM1026_REG_GPIO_CFG_0_3 + i/4, value); value = 0; } } /* Print the new config */ adm1026_print_gpio(client);}static struct adm1026_data *adm1026_update_device(struct device *dev){ struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); int i; long value, alarms, gpio; down(&data->update_lock); if (!data->valid || (jiffies - data->last_reading > ADM1026_DATA_INTERVAL)) { /* Things that change quickly */ dev_dbg(&client->dev,"(%d): Reading sensor values\n", client->id); for (i = 0;i <= 16;++i) { data->in[i] = adm1026_read_value(client, ADM1026_REG_IN[i]); } for (i = 0;i <= 7;++i) { data->fan[i] = adm1026_read_value(client, ADM1026_REG_FAN(i)); } for (i = 0;i <= 2;++i) { /* NOTE: temp[] is s8 and we assume 2's complement * "conversion" in the assignment */ data->temp[i] = adm1026_read_value(client, ADM1026_REG_TEMP[i]); } data->pwm1.pwm = adm1026_read_value(client, ADM1026_REG_PWM); data->analog_out = adm1026_read_value(client, ADM1026_REG_DAC); /* GPIO16 is MSbit of alarms, move it to gpio */ alarms = adm1026_read_value(client, ADM1026_REG_STATUS4); gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ alarms &= 0x7f; alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3); alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2); alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1); data->alarms = alarms; /* Read the GPIO values */ gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_8_15); gpio <<= 8; gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_STATUS_0_7); data->gpio = gpio; data->last_reading = jiffies; }; /* last_reading */ if (!data->valid || (jiffies - data->last_config > ADM1026_CONFIG_INTERVAL)) { /* Things that don't change often */ dev_dbg(&client->dev, "(%d): Reading config values\n", client->id); for (i = 0;i <= 16;++i) { data->in_min[i] = adm1026_read_value(client, ADM1026_REG_IN_MIN[i]); data->in_max[i] = adm1026_read_value(client, ADM1026_REG_IN_MAX[i]); } value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); for (i = 0;i <= 7;++i) { data->fan_min[i] = adm1026_read_value(client, ADM1026_REG_FAN_MIN(i)); data->fan_div[i] = DIV_FROM_REG(value & 0x03); value >>= 2; } for (i = 0; i <= 2; ++i) { /* NOTE: temp_xxx[] are s8 and we assume 2's * complement "conversion" in the assignment */ data->temp_min[i] = adm1026_read_value(client, ADM1026_REG_TEMP_MIN[i]); data->temp_max[i] = adm1026_read_value(client, ADM1026_REG_TEMP_MAX[i]); data->temp_tmin[i] = adm1026_read_value(client, ADM1026_REG_TEMP_TMIN[i]); data->temp_crit[i] = adm1026_read_value(client, ADM1026_REG_TEMP_THERM[i]); data->temp_offset[i] = adm1026_read_value(client, ADM1026_REG_TEMP_OFFSET[i]); } /* Read the STATUS/alarm masks */ alarms = adm1026_read_value(client, ADM1026_REG_MASK4); gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ alarms = (alarms & 0x7f) << 8; alarms |= adm1026_read_value(client, ADM1026_REG_MASK3); alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_MASK2); alarms <<= 8; alarms |= adm1026_read_value(client, ADM1026_REG_MASK1); data->alarm_mask = alarms; /* Read the GPIO values */ gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_8_15); gpio <<= 8; gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7); data->gpio_mask = gpio; /* Read various values from CONFIG1 */ data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); if (data->config1 & CFG1_PWM_AFC) { data->pwm1.enable = 2; data->pwm1.auto_pwm_min = PWM_MIN_FROM_REG(data->pwm1.pwm); } /* Read the GPIO config */ data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); data->gpio_config[16] = (data->config3 >> 6) & 0x03; value = 0; for (i = 0;i <= 15;++i) { if ((i & 0x03) == 0) { value = adm1026_read_value(client, ADM1026_REG_GPIO_CFG_0_3 + i/4); } data->gpio_config[i] = value & 0x03; value >>= 2; } data->last_config = jiffies; }; /* last_config */ dev_dbg(&client->dev, "(%d): Setting VID from GPIO11-15.\n", client->id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -