hwmon: (lm85) Add support for EMC6D103S
EMC6D103S is similar to EMC6D103, only it does not support registers 62[5:7], 6D[0:7], and 6E[0:7]. Register respective sysfs attributes and update affected registers for all other chips only. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Acked-by: Jean Delvare <khali@linux-fr.org>hifive-unleashed-5.1
parent
4f8ab430fa
commit
06923f8442
|
@ -26,6 +26,14 @@ Supported chips:
|
||||||
Prefix: 'emc6d102'
|
Prefix: 'emc6d102'
|
||||||
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
|
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
|
||||||
Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
|
Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
|
||||||
|
* SMSC EMC6D103
|
||||||
|
Prefix: 'emc6d103'
|
||||||
|
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
|
||||||
|
Datasheet: http://www.smsc.com/main/catalog/emc6d103.html
|
||||||
|
* SMSC EMC6D103S
|
||||||
|
Prefix: 'emc6d103s'
|
||||||
|
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
|
||||||
|
Datasheet: http://www.smsc.com/main/catalog/emc6d103s.html
|
||||||
|
|
||||||
Authors:
|
Authors:
|
||||||
Philip Pokorny <ppokorny@penguincomputing.com>,
|
Philip Pokorny <ppokorny@penguincomputing.com>,
|
||||||
|
@ -122,9 +130,11 @@ to be register compatible. The EMC6D100 offers all the features of the
|
||||||
EMC6D101 plus additional voltage monitoring and system control features.
|
EMC6D101 plus additional voltage monitoring and system control features.
|
||||||
Unfortunately it is not possible to distinguish between the package
|
Unfortunately it is not possible to distinguish between the package
|
||||||
versions on register level so these additional voltage inputs may read
|
versions on register level so these additional voltage inputs may read
|
||||||
zero. The EMC6D102 features addtional ADC bits thus extending precision
|
zero. EMC6D102 and EMC6D103 feature additional ADC bits thus extending precision
|
||||||
of voltage and temperature channels.
|
of voltage and temperature channels.
|
||||||
|
|
||||||
|
SMSC EMC6D103S is similar to EMC6D103, but does not support pwm#_auto_pwm_minctl
|
||||||
|
and temp#_auto_temp_off.
|
||||||
|
|
||||||
Hardware Configurations
|
Hardware Configurations
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
|
@ -41,7 +41,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||||
enum chips {
|
enum chips {
|
||||||
any_chip, lm85b, lm85c,
|
any_chip, lm85b, lm85c,
|
||||||
adm1027, adt7463, adt7468,
|
adm1027, adt7463, adt7468,
|
||||||
emc6d100, emc6d102, emc6d103
|
emc6d100, emc6d102, emc6d103, emc6d103s
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The LM85 registers */
|
/* The LM85 registers */
|
||||||
|
@ -350,6 +350,7 @@ static const struct i2c_device_id lm85_id[] = {
|
||||||
{ "emc6d101", emc6d100 },
|
{ "emc6d101", emc6d100 },
|
||||||
{ "emc6d102", emc6d102 },
|
{ "emc6d102", emc6d102 },
|
||||||
{ "emc6d103", emc6d103 },
|
{ "emc6d103", emc6d103 },
|
||||||
|
{ "emc6d103s", emc6d103s },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, lm85_id);
|
MODULE_DEVICE_TABLE(i2c, lm85_id);
|
||||||
|
@ -1068,13 +1069,7 @@ static struct attribute *lm85_attributes[] = {
|
||||||
&sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
|
&sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
|
||||||
&sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
|
&sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
|
||||||
&sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
|
&sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
|
||||||
&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
|
|
||||||
|
|
||||||
&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
|
|
||||||
&sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr,
|
&sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr,
|
&sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr,
|
||||||
&sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr,
|
&sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr,
|
||||||
|
@ -1095,6 +1090,26 @@ static const struct attribute_group lm85_group = {
|
||||||
.attrs = lm85_attributes,
|
.attrs = lm85_attributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct attribute *lm85_attributes_minctl[] = {
|
||||||
|
&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group lm85_group_minctl = {
|
||||||
|
.attrs = lm85_attributes_minctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute *lm85_attributes_temp_off[] = {
|
||||||
|
&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group lm85_group_temp_off = {
|
||||||
|
.attrs = lm85_attributes_temp_off,
|
||||||
|
};
|
||||||
|
|
||||||
static struct attribute *lm85_attributes_in4[] = {
|
static struct attribute *lm85_attributes_in4[] = {
|
||||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||||
&sensor_dev_attr_in4_min.dev_attr.attr,
|
&sensor_dev_attr_in4_min.dev_attr.attr,
|
||||||
|
@ -1242,16 +1257,9 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||||
case LM85_VERSTEP_EMC6D103_A1:
|
case LM85_VERSTEP_EMC6D103_A1:
|
||||||
type_name = "emc6d103";
|
type_name = "emc6d103";
|
||||||
break;
|
break;
|
||||||
/*
|
|
||||||
* Registers apparently missing in EMC6D103S/EMC6D103:A2
|
|
||||||
* compared to EMC6D103:A0, EMC6D103:A1, and EMC6D102
|
|
||||||
* (according to the data sheets), but used unconditionally
|
|
||||||
* in the driver: 62[5:7], 6D[0:7], and 6E[0:7].
|
|
||||||
* So skip EMC6D103S for now.
|
|
||||||
case LM85_VERSTEP_EMC6D103S:
|
case LM85_VERSTEP_EMC6D103S:
|
||||||
type_name = "emc6d103s";
|
type_name = "emc6d103s";
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&adapter->dev,
|
dev_dbg(&adapter->dev,
|
||||||
|
@ -1267,6 +1275,10 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||||
static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
|
static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
|
||||||
{
|
{
|
||||||
sysfs_remove_group(&client->dev.kobj, &lm85_group);
|
sysfs_remove_group(&client->dev.kobj, &lm85_group);
|
||||||
|
if (data->type != emc6d103s) {
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl);
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off);
|
||||||
|
}
|
||||||
if (!data->has_vid5)
|
if (!data->has_vid5)
|
||||||
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
|
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
|
||||||
if (data->type == emc6d100)
|
if (data->type == emc6d100)
|
||||||
|
@ -1295,6 +1307,7 @@ static int lm85_probe(struct i2c_client *client,
|
||||||
case emc6d100:
|
case emc6d100:
|
||||||
case emc6d102:
|
case emc6d102:
|
||||||
case emc6d103:
|
case emc6d103:
|
||||||
|
case emc6d103s:
|
||||||
data->freq_map = adm1027_freq_map;
|
data->freq_map = adm1027_freq_map;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1312,6 +1325,17 @@ static int lm85_probe(struct i2c_client *client,
|
||||||
if (err)
|
if (err)
|
||||||
goto err_kfree;
|
goto err_kfree;
|
||||||
|
|
||||||
|
/* minctl and temp_off exist on all chips except emc6d103s */
|
||||||
|
if (data->type != emc6d103s) {
|
||||||
|
err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
|
||||||
|
if (err)
|
||||||
|
goto err_kfree;
|
||||||
|
err = sysfs_create_group(&client->dev.kobj,
|
||||||
|
&lm85_group_temp_off);
|
||||||
|
if (err)
|
||||||
|
goto err_kfree;
|
||||||
|
}
|
||||||
|
|
||||||
/* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
|
/* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
|
||||||
as a sixth digital VID input rather than an analog input. */
|
as a sixth digital VID input rather than an analog input. */
|
||||||
if (data->type == adt7463 || data->type == adt7468) {
|
if (data->type == adt7463 || data->type == adt7468) {
|
||||||
|
@ -1475,7 +1499,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
|
||||||
/* More alarm bits */
|
/* More alarm bits */
|
||||||
data->alarms |= lm85_read_value(client,
|
data->alarms |= lm85_read_value(client,
|
||||||
EMC6D100_REG_ALARM3) << 16;
|
EMC6D100_REG_ALARM3) << 16;
|
||||||
} else if (data->type == emc6d102 || data->type == emc6d103) {
|
} else if (data->type == emc6d102 || data->type == emc6d103 ||
|
||||||
|
data->type == emc6d103s) {
|
||||||
/* Have to read LSB bits after the MSB ones because
|
/* Have to read LSB bits after the MSB ones because
|
||||||
the reading of the MSB bits has frozen the
|
the reading of the MSB bits has frozen the
|
||||||
LSBs (backward from the ADM1027).
|
LSBs (backward from the ADM1027).
|
||||||
|
@ -1560,17 +1585,19 @@ static struct lm85_data *lm85_update_device(struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
|
if (data->type != emc6d103s) {
|
||||||
data->autofan[0].min_off = (i & 0x20) != 0;
|
i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
|
||||||
data->autofan[1].min_off = (i & 0x40) != 0;
|
data->autofan[0].min_off = (i & 0x20) != 0;
|
||||||
data->autofan[2].min_off = (i & 0x80) != 0;
|
data->autofan[1].min_off = (i & 0x40) != 0;
|
||||||
|
data->autofan[2].min_off = (i & 0x80) != 0;
|
||||||
|
|
||||||
i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
|
i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
|
||||||
data->zone[0].hyst = i >> 4;
|
data->zone[0].hyst = i >> 4;
|
||||||
data->zone[1].hyst = i & 0x0f;
|
data->zone[1].hyst = i & 0x0f;
|
||||||
|
|
||||||
i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
|
i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
|
||||||
data->zone[2].hyst = i >> 4;
|
data->zone[2].hyst = i >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
data->last_config = jiffies;
|
data->last_config = jiffies;
|
||||||
} /* last_config */
|
} /* last_config */
|
||||||
|
|
Loading…
Reference in New Issue