--- zzzz-none-000/linux-3.10.107/drivers/hwmon/lm75.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/hwmon/lm75.c 2021-02-04 17:41:59.000000000 +0000 @@ -27,6 +27,13 @@ #include #include #include +#include +#include + +#if IS_ENABLED(CONFIG_AVM_POWER) +#include +#endif + #include "lm75.h" @@ -39,8 +46,10 @@ ds1775, ds75, ds7505, + g751, lm75, lm75a, + lm75b, max6625, max6626, mcp980x, @@ -49,9 +58,11 @@ tmp100, tmp101, tmp105, + tmp112, tmp175, tmp275, tmp75, + tmp75c, }; /* Addresses scanned */ @@ -69,7 +80,9 @@ /* Each client has this additional data */ struct lm75_data { + struct i2c_client *client; struct device *hwmon_dev; + struct thermal_zone_device *tz; struct mutex update_lock; u8 orig_conf; u8 resolution; /* In bits, between 9 and 12 */ @@ -81,6 +94,9 @@ 0 = input 1 = max 2 = hyst */ +#if IS_ENABLED(CONFIG_AVM_POWER) + void *avm_power_handle; +#endif }; static int lm75_read_value(struct i2c_client *client, u8 reg); @@ -90,30 +106,44 @@ /*-----------------------------------------------------------------------*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + /* sysfs attributes for hwmon */ +static int lm75_read_temp(void *dev, int *temp) +{ + struct lm75_data *data = lm75_update_device(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + *temp = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm75_data *data = lm75_update_device(dev); - long temp; if (IS_ERR(data)) return PTR_ERR(data); - temp = ((data->temp[attr->index] >> (16 - data->resolution)) * 1000) - >> (data->resolution - 8); - - return sprintf(buf, "%ld\n", temp); + return sprintf(buf, "%ld\n", lm75_reg_to_mc(data->temp[attr->index], + data->resolution)); } static ssize_t set_temp(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct lm75_data *data = i2c_get_clientdata(client); + struct lm75_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = attr->index; long temp; int error; @@ -147,18 +177,33 @@ show_temp, set_temp, 2); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static struct attribute *lm75_attributes[] = { +static struct attribute *lm75_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, NULL }; +ATTRIBUTE_GROUPS(lm75); -static const struct attribute_group lm75_group = { - .attrs = lm75_attributes, +static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = { + .get_temp = lm75_read_temp, }; +#if IS_ENABLED(CONFIG_AVM_POWER) +static int lm75_avm_power_cb(void *handle, void *dev, int *temp) +{ + struct lm75_data *data = lm75_update_device(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + *temp = lm75_reg_to_mc(data->temp[0], data->resolution) / 100; + + return 0; +} +#endif + /*-----------------------------------------------------------------------*/ /* device probe and removal */ @@ -166,6 +211,7 @@ static int lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct lm75_data *data; int status; u8 set_mask, clr_mask; @@ -176,10 +222,11 @@ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return -EIO; - data = devm_kzalloc(&client->dev, sizeof(struct lm75_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct lm75_data), GFP_KERNEL); if (!data) return -ENOMEM; + data->client = client; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -208,11 +255,16 @@ data->resolution = 12; data->sample_time = HZ / 4; break; + case g751: case lm75: case lm75a: data->resolution = 9; data->sample_time = HZ / 2; break; + case lm75b: + data->resolution = 11; + data->sample_time = HZ / 4; + break; case max6625: data->resolution = 9; data->sample_time = HZ / 4; @@ -236,6 +288,12 @@ data->sample_time = HZ; clr_mask |= 1 << 7; /* not one-shot mode */ break; + case tmp112: + set_mask |= 3 << 5; /* 12-bit mode */ + clr_mask |= 1 << 7; /* not one-shot mode */ + data->resolution = 12; + data->sample_time = HZ / 4; + break; case tmp105: case tmp175: case tmp275: @@ -245,12 +303,17 @@ data->resolution = 12; data->sample_time = HZ / 2; break; + case tmp75c: + clr_mask |= 1 << 5; /* not one-shot mode */ + data->resolution = 12; + data->sample_time = HZ / 4; + break; } /* configure as specified */ status = lm75_read_value(client, LM75_REG_CONF); if (status < 0) { - dev_dbg(&client->dev, "Can't read config? %d\n", status); + dev_dbg(dev, "Can't read config? %d\n", status); return status; } data->orig_conf = status; @@ -258,35 +321,37 @@ new |= set_mask; if (status != new) lm75_write_value(client, LM75_REG_CONF, new); - dev_dbg(&client->dev, "Config %02x\n", new); + dev_dbg(dev, "Config %02x\n", new); - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &lm75_group); - if (status) - return status; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } + data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + data, lm75_groups); + if (IS_ERR(data->hwmon_dev)) + return PTR_ERR(data->hwmon_dev); + + data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 0, + data->hwmon_dev, + &lm75_of_thermal_ops); + if (IS_ERR(data->tz)) + data->tz = NULL; + +#if IS_ENABLED(CONFIG_AVM_POWER) + data->avm_power_handle = TemperaturSensorRegister(client->name, lm75_avm_power_cb, dev); + if (IS_ERR(data->avm_power_handle)) + data->avm_power_handle = NULL; +#endif - dev_info(&client->dev, "%s: sensor '%s'\n", + dev_info(dev, "%s: sensor '%s'\n", dev_name(data->hwmon_dev), client->name); return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &lm75_group); - return status; } static int lm75_remove(struct i2c_client *client) { struct lm75_data *data = i2c_get_clientdata(client); + thermal_zone_of_sensor_unregister(data->hwmon_dev, data->tz); hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm75_group); lm75_write_value(client, LM75_REG_CONF, data->orig_conf); return 0; } @@ -296,8 +361,10 @@ { "ds1775", ds1775, }, { "ds75", ds75, }, { "ds7505", ds7505, }, + { "g751", g751, }, { "lm75", lm75, }, { "lm75a", lm75a, }, + { "lm75b", lm75b, }, { "max6625", max6625, }, { "max6626", max6626, }, { "mcp980x", mcp980x, }, @@ -306,9 +373,11 @@ { "tmp100", tmp100, }, { "tmp101", tmp101, }, { "tmp105", tmp105, }, + { "tmp112", tmp112, }, { "tmp175", tmp175, }, { "tmp275", tmp275, }, { "tmp75", tmp75, }, + { "tmp75c", tmp75c, }, { /* LIST END */ } }; MODULE_DEVICE_TABLE(i2c, lm75_ids); @@ -384,6 +453,12 @@ || i2c_smbus_read_byte_data(new_client, 7) != os) return -ENODEV; } + /* + * It is very unlikely that this is a LM75 if both + * hysteresis and temperature limit registers are 0. + */ + if (hyst == 0 && os == 0) + return -ENODEV; /* Addresses cycling */ for (i = 8; i <= 248; i += 40) { @@ -479,8 +554,8 @@ static struct lm75_data *lm75_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct lm75_data *data = i2c_get_clientdata(client); + struct lm75_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; struct lm75_data *ret = data; mutex_lock(&data->update_lock);