|
@@ -298,37 +298,6 @@ struct adm1026_data {
|
|
u8 config3; /* Register value */
|
|
u8 config3; /* Register value */
|
|
};
|
|
};
|
|
|
|
|
|
-static int adm1026_probe(struct i2c_client *client,
|
|
|
|
- const struct i2c_device_id *id);
|
|
|
|
-static int adm1026_detect(struct i2c_client *client,
|
|
|
|
- struct i2c_board_info *info);
|
|
|
|
-static int adm1026_remove(struct i2c_client *client);
|
|
|
|
-static int adm1026_read_value(struct i2c_client *client, u8 reg);
|
|
|
|
-static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
|
|
|
|
-static void adm1026_print_gpio(struct i2c_client *client);
|
|
|
|
-static void adm1026_fixup_gpio(struct i2c_client *client);
|
|
|
|
-static struct adm1026_data *adm1026_update_device(struct device *dev);
|
|
|
|
-static void adm1026_init_client(struct i2c_client *client);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static const struct i2c_device_id adm1026_id[] = {
|
|
|
|
- { "adm1026", 0 },
|
|
|
|
- { }
|
|
|
|
-};
|
|
|
|
-MODULE_DEVICE_TABLE(i2c, adm1026_id);
|
|
|
|
-
|
|
|
|
-static struct i2c_driver adm1026_driver = {
|
|
|
|
- .class = I2C_CLASS_HWMON,
|
|
|
|
- .driver = {
|
|
|
|
- .name = "adm1026",
|
|
|
|
- },
|
|
|
|
- .probe = adm1026_probe,
|
|
|
|
- .remove = adm1026_remove,
|
|
|
|
- .id_table = adm1026_id,
|
|
|
|
- .detect = adm1026_detect,
|
|
|
|
- .address_list = normal_i2c,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
static int adm1026_read_value(struct i2c_client *client, u8 reg)
|
|
static int adm1026_read_value(struct i2c_client *client, u8 reg)
|
|
{
|
|
{
|
|
int res;
|
|
int res;
|
|
@@ -357,208 +326,6 @@ static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
|
|
-static void adm1026_init_client(struct i2c_client *client)
|
|
|
|
-{
|
|
|
|
- int value, i;
|
|
|
|
- struct adm1026_data *data = i2c_get_clientdata(client);
|
|
|
|
-
|
|
|
|
- dev_dbg(&client->dev, "Initializing device\n");
|
|
|
|
- /* 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, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
|
|
|
|
- data->config1);
|
|
|
|
- if ((data->config1 & CFG1_MONITOR) == 0) {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "Monitoring not currently enabled.\n");
|
|
|
|
- }
|
|
|
|
- if (data->config1 & CFG1_INT_ENABLE) {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "SMBALERT interrupts are enabled.\n");
|
|
|
|
- }
|
|
|
|
- if (data->config1 & CFG1_AIN8_9) {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "in8 and in9 enabled. temp3 disabled.\n");
|
|
|
|
- } else {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "temp3 enabled. in8 and in9 disabled.\n");
|
|
|
|
- }
|
|
|
|
- if (data->config1 & CFG1_THERM_HOT) {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "Automatic THERM, PWM, and temp limits enabled.\n");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (data->config3 & CFG3_GPIO16_ENABLE) {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "GPIO16 enabled. THERM pin disabled.\n");
|
|
|
|
- } else {
|
|
|
|
- dev_dbg(&client->dev,
|
|
|
|
- "THERM pin enabled. GPIO16 disabled.\n");
|
|
|
|
- }
|
|
|
|
- if (data->config3 & CFG3_VREF_250)
|
|
|
|
- dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
|
|
|
|
- else
|
|
|
|
- dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
|
|
|
|
- /* 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.
|
|
|
|
- */
|
|
|
|
- if (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, "Setting CONFIG to: 0x%02x\n", 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;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void adm1026_print_gpio(struct i2c_client *client)
|
|
|
|
-{
|
|
|
|
- struct adm1026_data *data = i2c_get_clientdata(client);
|
|
|
|
- int i;
|
|
|
|
-
|
|
|
|
- dev_dbg(&client->dev, "GPIO config is:\n");
|
|
|
|
- for (i = 0; i <= 7; ++i) {
|
|
|
|
- if (data->config2 & (1 << i)) {
|
|
|
|
- dev_dbg(&client->dev, "\t%sGP%s%d\n",
|
|
|
|
- data->gpio_config[i] & 0x02 ? "" : "!",
|
|
|
|
- data->gpio_config[i] & 0x01 ? "OUT" : "IN",
|
|
|
|
- i);
|
|
|
|
- } else {
|
|
|
|
- dev_dbg(&client->dev, "\tFAN%d\n", i);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- for (i = 8; i <= 15; ++i) {
|
|
|
|
- dev_dbg(&client->dev, "\t%sGP%s%d\n",
|
|
|
|
- data->gpio_config[i] & 0x02 ? "" : "!",
|
|
|
|
- data->gpio_config[i] & 0x01 ? "OUT" : "IN",
|
|
|
|
- i);
|
|
|
|
- }
|
|
|
|
- if (data->config3 & CFG3_GPIO16_ENABLE) {
|
|
|
|
- dev_dbg(&client->dev, "\t%sGP%s16\n",
|
|
|
|
- data->gpio_config[16] & 0x02 ? "" : "!",
|
|
|
|
- data->gpio_config[16] & 0x01 ? "OUT" : "IN");
|
|
|
|
- } else {
|
|
|
|
- /* GPIO16 is THERM */
|
|
|
|
- dev_dbg(&client->dev, "\tTHERM\n");
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static 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)
|
|
static struct adm1026_data *adm1026_update_device(struct device *dev)
|
|
{
|
|
{
|
|
struct i2c_client *client = to_i2c_client(dev);
|
|
struct i2c_client *client = to_i2c_client(dev);
|
|
@@ -1829,6 +1596,207 @@ static int adm1026_detect(struct i2c_client *client,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void adm1026_print_gpio(struct i2c_client *client)
|
|
|
|
+{
|
|
|
|
+ struct adm1026_data *data = i2c_get_clientdata(client);
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ dev_dbg(&client->dev, "GPIO config is:\n");
|
|
|
|
+ for (i = 0; i <= 7; ++i) {
|
|
|
|
+ if (data->config2 & (1 << i)) {
|
|
|
|
+ dev_dbg(&client->dev, "\t%sGP%s%d\n",
|
|
|
|
+ data->gpio_config[i] & 0x02 ? "" : "!",
|
|
|
|
+ data->gpio_config[i] & 0x01 ? "OUT" : "IN",
|
|
|
|
+ i);
|
|
|
|
+ } else {
|
|
|
|
+ dev_dbg(&client->dev, "\tFAN%d\n", i);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (i = 8; i <= 15; ++i) {
|
|
|
|
+ dev_dbg(&client->dev, "\t%sGP%s%d\n",
|
|
|
|
+ data->gpio_config[i] & 0x02 ? "" : "!",
|
|
|
|
+ data->gpio_config[i] & 0x01 ? "OUT" : "IN",
|
|
|
|
+ i);
|
|
|
|
+ }
|
|
|
|
+ if (data->config3 & CFG3_GPIO16_ENABLE) {
|
|
|
|
+ dev_dbg(&client->dev, "\t%sGP%s16\n",
|
|
|
|
+ data->gpio_config[16] & 0x02 ? "" : "!",
|
|
|
|
+ data->gpio_config[16] & 0x01 ? "OUT" : "IN");
|
|
|
|
+ } else {
|
|
|
|
+ /* GPIO16 is THERM */
|
|
|
|
+ dev_dbg(&client->dev, "\tTHERM\n");
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static 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 void adm1026_init_client(struct i2c_client *client)
|
|
|
|
+{
|
|
|
|
+ int value, i;
|
|
|
|
+ struct adm1026_data *data = i2c_get_clientdata(client);
|
|
|
|
+
|
|
|
|
+ dev_dbg(&client->dev, "Initializing device\n");
|
|
|
|
+ /* 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, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
|
|
|
|
+ data->config1);
|
|
|
|
+ if ((data->config1 & CFG1_MONITOR) == 0) {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "Monitoring not currently enabled.\n");
|
|
|
|
+ }
|
|
|
|
+ if (data->config1 & CFG1_INT_ENABLE) {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "SMBALERT interrupts are enabled.\n");
|
|
|
|
+ }
|
|
|
|
+ if (data->config1 & CFG1_AIN8_9) {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "in8 and in9 enabled. temp3 disabled.\n");
|
|
|
|
+ } else {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "temp3 enabled. in8 and in9 disabled.\n");
|
|
|
|
+ }
|
|
|
|
+ if (data->config1 & CFG1_THERM_HOT) {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "Automatic THERM, PWM, and temp limits enabled.\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (data->config3 & CFG3_GPIO16_ENABLE) {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "GPIO16 enabled. THERM pin disabled.\n");
|
|
|
|
+ } else {
|
|
|
|
+ dev_dbg(&client->dev,
|
|
|
|
+ "THERM pin enabled. GPIO16 disabled.\n");
|
|
|
|
+ }
|
|
|
|
+ if (data->config3 & CFG3_VREF_250)
|
|
|
|
+ dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
|
|
|
|
+ else
|
|
|
|
+ dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
|
|
|
|
+ /* 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.
|
|
|
|
+ */
|
|
|
|
+ if (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, "Setting CONFIG to: 0x%02x\n", 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;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static int adm1026_probe(struct i2c_client *client,
|
|
static int adm1026_probe(struct i2c_client *client,
|
|
const struct i2c_device_id *id)
|
|
const struct i2c_device_id *id)
|
|
{
|
|
{
|
|
@@ -1892,6 +1860,24 @@ static int adm1026_remove(struct i2c_client *client)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static const struct i2c_device_id adm1026_id[] = {
|
|
|
|
+ { "adm1026", 0 },
|
|
|
|
+ { }
|
|
|
|
+};
|
|
|
|
+MODULE_DEVICE_TABLE(i2c, adm1026_id);
|
|
|
|
+
|
|
|
|
+static struct i2c_driver adm1026_driver = {
|
|
|
|
+ .class = I2C_CLASS_HWMON,
|
|
|
|
+ .driver = {
|
|
|
|
+ .name = "adm1026",
|
|
|
|
+ },
|
|
|
|
+ .probe = adm1026_probe,
|
|
|
|
+ .remove = adm1026_remove,
|
|
|
|
+ .id_table = adm1026_id,
|
|
|
|
+ .detect = adm1026_detect,
|
|
|
|
+ .address_list = normal_i2c,
|
|
|
|
+};
|
|
|
|
+
|
|
module_i2c_driver(adm1026_driver);
|
|
module_i2c_driver(adm1026_driver);
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|