Loading drivers/hwmon/Kconfig +0 −1 Original line number Diff line number Diff line Loading @@ -969,7 +969,6 @@ config SENSORS_LM73 config SENSORS_LM75 tristate "National Semiconductor LM75 and compatibles" depends on I2C depends on THERMAL || !THERMAL_OF select REGMAP_I2C help If you say yes here you get support for one common type of Loading drivers/hwmon/lm75.c +116 −69 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ #include <linux/err.h> #include <linux/of.h> #include <linux/regmap.h> #include <linux/thermal.h> #include "lm75.h" Loading Loading @@ -88,56 +87,75 @@ 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) static int lm75_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { struct lm75_data *data = dev_get_drvdata(dev); unsigned int _temp; int err; err = regmap_read(data->regmap, LM75_REG_TEMP, &_temp); unsigned int regval; int err, reg; switch (type) { case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: *val = data->sample_time; break;; default: return -EINVAL; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: reg = LM75_REG_TEMP; break; case hwmon_temp_max: reg = LM75_REG_MAX; break; case hwmon_temp_max_hyst: reg = LM75_REG_HYST; break; default: return -EINVAL; } err = regmap_read(data->regmap, reg, ®val); if (err < 0) return err; *temp = lm75_reg_to_mc(_temp, data->resolution); *val = lm75_reg_to_mc(regval, data->resolution); break; default: return -EINVAL; } return 0; } static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) static int lm75_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long temp) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm75_data *data = dev_get_drvdata(dev); unsigned int temp = 0; int err; u8 resolution; int reg; err = regmap_read(data->regmap, attr->index, &temp); if (err < 0) return err; if (type != hwmon_temp) return -EINVAL; return sprintf(buf, "%ld\n", lm75_reg_to_mc(temp, data->resolution)); switch (attr) { case hwmon_temp_max: reg = LM75_REG_MAX; break; case hwmon_temp_max_hyst: reg = LM75_REG_HYST; break; default: return -EINVAL; } 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 lm75_data *data = dev_get_drvdata(dev); long temp; int error; u8 resolution; error = kstrtol(buf, 10, &temp); if (error) return error; /* * Resolution of limit registers is assumed to be the same as the * temperature input register resolution unless given explicitly. */ if (attr->index && data->resolution_limits) if (data->resolution_limits) resolution = data->resolution_limits; else resolution = data->resolution; Loading @@ -145,45 +163,77 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); temp = DIV_ROUND_CLOSEST(temp << (resolution - 8), 1000) << (16 - resolution); error = regmap_write(data->regmap, attr->index, temp); if (error < 0) return error; return count; return regmap_write(data->regmap, reg, temp); } static ssize_t show_update_interval(struct device *dev, struct device_attribute *da, char *buf) static umode_t lm75_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { struct lm75_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->sample_time); switch (type) { case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: return S_IRUGO; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: return S_IRUGO; case hwmon_temp_max: case hwmon_temp_max_hyst: return S_IRUGO | S_IWUSR; } break; default: break; } return 0; } /*-----------------------------------------------------------------------*/ static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, LM75_REG_MAX); static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp, set_temp, LM75_REG_HYST); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, LM75_REG_TEMP); static DEVICE_ATTR(update_interval, S_IRUGO, show_update_interval, NULL); /* device probe and removal */ 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, &dev_attr_update_interval.attr, /* chip configuration */ NULL static const u32 lm75_chip_config[] = { HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL, 0 }; ATTRIBUTE_GROUPS(lm75); static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = { .get_temp = lm75_read_temp, static const struct hwmon_channel_info lm75_chip = { .type = hwmon_chip, .config = lm75_chip_config, }; /*-----------------------------------------------------------------------*/ static const u32 lm75_temp_config[] = { HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST, 0 }; /* device probe and removal */ static const struct hwmon_channel_info lm75_temp = { .type = hwmon_temp, .config = lm75_temp_config, }; static const struct hwmon_channel_info *lm75_info[] = { &lm75_chip, &lm75_temp, NULL }; static const struct hwmon_ops lm75_hwmon_ops = { .is_visible = lm75_is_visible, .read = lm75_read, .write = lm75_write, }; static const struct hwmon_chip_info lm75_chip_info = { .ops = &lm75_hwmon_ops, .info = lm75_info, }; static bool lm75_is_writeable_reg(struct device *dev, unsigned int reg) { Loading Loading @@ -337,15 +387,12 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_dbg(dev, "Config %02x\n", new); hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, lm75_groups); hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, &lm75_chip_info, NULL); if (IS_ERR(hwmon_dev)) return PTR_ERR(hwmon_dev); devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, &lm75_of_thermal_ops); dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), client->name); return 0; Loading Loading
drivers/hwmon/Kconfig +0 −1 Original line number Diff line number Diff line Loading @@ -969,7 +969,6 @@ config SENSORS_LM73 config SENSORS_LM75 tristate "National Semiconductor LM75 and compatibles" depends on I2C depends on THERMAL || !THERMAL_OF select REGMAP_I2C help If you say yes here you get support for one common type of Loading
drivers/hwmon/lm75.c +116 −69 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ #include <linux/err.h> #include <linux/of.h> #include <linux/regmap.h> #include <linux/thermal.h> #include "lm75.h" Loading Loading @@ -88,56 +87,75 @@ 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) static int lm75_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { struct lm75_data *data = dev_get_drvdata(dev); unsigned int _temp; int err; err = regmap_read(data->regmap, LM75_REG_TEMP, &_temp); unsigned int regval; int err, reg; switch (type) { case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: *val = data->sample_time; break;; default: return -EINVAL; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: reg = LM75_REG_TEMP; break; case hwmon_temp_max: reg = LM75_REG_MAX; break; case hwmon_temp_max_hyst: reg = LM75_REG_HYST; break; default: return -EINVAL; } err = regmap_read(data->regmap, reg, ®val); if (err < 0) return err; *temp = lm75_reg_to_mc(_temp, data->resolution); *val = lm75_reg_to_mc(regval, data->resolution); break; default: return -EINVAL; } return 0; } static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) static int lm75_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long temp) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm75_data *data = dev_get_drvdata(dev); unsigned int temp = 0; int err; u8 resolution; int reg; err = regmap_read(data->regmap, attr->index, &temp); if (err < 0) return err; if (type != hwmon_temp) return -EINVAL; return sprintf(buf, "%ld\n", lm75_reg_to_mc(temp, data->resolution)); switch (attr) { case hwmon_temp_max: reg = LM75_REG_MAX; break; case hwmon_temp_max_hyst: reg = LM75_REG_HYST; break; default: return -EINVAL; } 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 lm75_data *data = dev_get_drvdata(dev); long temp; int error; u8 resolution; error = kstrtol(buf, 10, &temp); if (error) return error; /* * Resolution of limit registers is assumed to be the same as the * temperature input register resolution unless given explicitly. */ if (attr->index && data->resolution_limits) if (data->resolution_limits) resolution = data->resolution_limits; else resolution = data->resolution; Loading @@ -145,45 +163,77 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); temp = DIV_ROUND_CLOSEST(temp << (resolution - 8), 1000) << (16 - resolution); error = regmap_write(data->regmap, attr->index, temp); if (error < 0) return error; return count; return regmap_write(data->regmap, reg, temp); } static ssize_t show_update_interval(struct device *dev, struct device_attribute *da, char *buf) static umode_t lm75_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { struct lm75_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->sample_time); switch (type) { case hwmon_chip: switch (attr) { case hwmon_chip_update_interval: return S_IRUGO; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: return S_IRUGO; case hwmon_temp_max: case hwmon_temp_max_hyst: return S_IRUGO | S_IWUSR; } break; default: break; } return 0; } /*-----------------------------------------------------------------------*/ static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, LM75_REG_MAX); static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp, set_temp, LM75_REG_HYST); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, LM75_REG_TEMP); static DEVICE_ATTR(update_interval, S_IRUGO, show_update_interval, NULL); /* device probe and removal */ 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, &dev_attr_update_interval.attr, /* chip configuration */ NULL static const u32 lm75_chip_config[] = { HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL, 0 }; ATTRIBUTE_GROUPS(lm75); static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = { .get_temp = lm75_read_temp, static const struct hwmon_channel_info lm75_chip = { .type = hwmon_chip, .config = lm75_chip_config, }; /*-----------------------------------------------------------------------*/ static const u32 lm75_temp_config[] = { HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST, 0 }; /* device probe and removal */ static const struct hwmon_channel_info lm75_temp = { .type = hwmon_temp, .config = lm75_temp_config, }; static const struct hwmon_channel_info *lm75_info[] = { &lm75_chip, &lm75_temp, NULL }; static const struct hwmon_ops lm75_hwmon_ops = { .is_visible = lm75_is_visible, .read = lm75_read, .write = lm75_write, }; static const struct hwmon_chip_info lm75_chip_info = { .ops = &lm75_hwmon_ops, .info = lm75_info, }; static bool lm75_is_writeable_reg(struct device *dev, unsigned int reg) { Loading Loading @@ -337,15 +387,12 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_dbg(dev, "Config %02x\n", new); hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, lm75_groups); hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, &lm75_chip_info, NULL); if (IS_ERR(hwmon_dev)) return PTR_ERR(hwmon_dev); devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, &lm75_of_thermal_ops); dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), client->name); return 0; Loading