diff options
Diffstat (limited to 'drivers/hwmon/ltc2947-core.c')
| -rw-r--r-- | drivers/hwmon/ltc2947-core.c | 146 |
1 files changed, 52 insertions, 94 deletions
diff --git a/drivers/hwmon/ltc2947-core.c b/drivers/hwmon/ltc2947-core.c index bb3f7749a0b0..ad7120d1e469 100644 --- a/drivers/hwmon/ltc2947-core.c +++ b/drivers/hwmon/ltc2947-core.c @@ -9,9 +9,10 @@ #include <linux/clk.h> #include <linux/device.h> #include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> #include <linux/module.h> -#include <linux/of.h> +#include <linux/math64.h> +#include <linux/mod_devicetable.h> +#include <linux/property.h> #include <linux/regmap.h> #include "ltc2947.h" @@ -119,12 +120,6 @@ struct ltc2947_data { struct regmap *map; struct device *dev; - /* - * The mutex is needed because the device has 2 memory pages. When - * reading/writing the correct page needs to be set so that, the - * complete sequence select_page->read/write needs to be protected. - */ - struct mutex lock; u32 lsb_energy; bool gpio_out; }; @@ -180,13 +175,9 @@ static int ltc2947_val_read(struct ltc2947_data *st, const u8 reg, int ret; u64 __val = 0; - mutex_lock(&st->lock); - ret = regmap_write(st->map, LTC2947_REG_PAGE_CTRL, page); - if (ret) { - mutex_unlock(&st->lock); + if (ret) return ret; - } dev_dbg(st->dev, "Read val, reg:%02X, p:%d sz:%zu\n", reg, page, size); @@ -206,8 +197,6 @@ static int ltc2947_val_read(struct ltc2947_data *st, const u8 reg, break; } - mutex_unlock(&st->lock); - if (ret) return ret; @@ -241,13 +230,10 @@ static int ltc2947_val_write(struct ltc2947_data *st, const u8 reg, { int ret; - mutex_lock(&st->lock); /* set device on correct page */ ret = regmap_write(st->map, LTC2947_REG_PAGE_CTRL, page); - if (ret) { - mutex_unlock(&st->lock); + if (ret) return ret; - } dev_dbg(st->dev, "Write val, r:%02X, p:%d, sz:%zu, val:%016llX\n", reg, page, size, val); @@ -264,8 +250,6 @@ static int ltc2947_val_write(struct ltc2947_data *st, const u8 reg, break; } - mutex_unlock(&st->lock); - return ret; } @@ -294,11 +278,9 @@ static int ltc2947_alarm_read(struct ltc2947_data *st, const u8 reg, memset(alarms, 0, sizeof(alarms)); - mutex_lock(&st->lock); - ret = regmap_write(st->map, LTC2947_REG_PAGE_CTRL, LTC2947_PAGE0); if (ret) - goto unlock; + return ret; dev_dbg(st->dev, "Read alarm, reg:%02X, mask:%02X\n", reg, mask); /* @@ -309,31 +291,11 @@ static int ltc2947_alarm_read(struct ltc2947_data *st, const u8 reg, ret = regmap_bulk_read(st->map, LTC2947_REG_STATUS, alarms, sizeof(alarms)); if (ret) - goto unlock; + return ret; /* get the alarm */ *val = !!(alarms[offset] & mask); -unlock: - mutex_unlock(&st->lock); - return ret; -} - -static ssize_t ltc2947_show_value(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct ltc2947_data *st = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int ret; - s64 val = 0; - - ret = ltc2947_val_read(st, attr->index, LTC2947_PAGE0, 6, &val); - if (ret) - return ret; - - /* value in microJoule. st->lsb_energy was multiplied by 10E9 */ - val = div_s64(val * st->lsb_energy, 1000); - - return sprintf(buf, "%lld\n", val); + return 0; } static int ltc2947_read_temp(struct device *dev, const u32 attr, long *val, @@ -396,7 +358,7 @@ static int ltc2947_read_temp(struct device *dev, const u32 attr, long *val, return ret; /* in milidegrees celcius, temp is given by: */ - *val = (__val * 204) + 550; + *val = (__val * 204) + 5500; return 0; } @@ -587,6 +549,23 @@ static int ltc2947_read_in(struct device *dev, const u32 attr, long *val, return 0; } +static int ltc2947_read_energy(struct device *dev, s64 *val, const int channel) +{ + int reg = channel ? LTC2947_REG_ENERGY2 : LTC2947_REG_ENERGY1; + struct ltc2947_data *st = dev_get_drvdata(dev); + s64 __val = 0; + int ret; + + ret = ltc2947_val_read(st, reg, LTC2947_PAGE0, 6, &__val); + if (ret) + return ret; + + /* value in microJoule. st->lsb_energy was multiplied by 10E9 */ + *val = DIV_S64_ROUND_CLOSEST(__val * st->lsb_energy, 1000); + + return 0; +} + static int ltc2947_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { @@ -599,6 +578,8 @@ static int ltc2947_read(struct device *dev, enum hwmon_sensor_types type, return ltc2947_read_power(dev, attr, val); case hwmon_temp: return ltc2947_read_temp(dev, attr, val, channel); + case hwmon_energy64: + return ltc2947_read_energy(dev, (s64 *)val, channel); default: return -ENOTSUPP; } @@ -896,12 +877,14 @@ static umode_t ltc2947_is_visible(const void *data, return ltc2947_power_is_visible(attr); case hwmon_temp: return ltc2947_temp_is_visible(attr); + case hwmon_energy64: + return 0444; default: return 0; } } -static const struct hwmon_channel_info *ltc2947_info[] = { +static const struct hwmon_channel_info * const ltc2947_info[] = { HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MAX | HWMON_I_MIN | HWMON_I_RESET_HISTORY | @@ -928,6 +911,9 @@ static const struct hwmon_channel_info *ltc2947_info[] = { HWMON_T_LABEL, HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | HWMON_T_MAX | HWMON_T_MIN | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(energy64, + HWMON_E_INPUT, + HWMON_E_INPUT), NULL }; @@ -943,26 +929,6 @@ static const struct hwmon_chip_info ltc2947_chip_info = { .info = ltc2947_info, }; -/* energy attributes are 6bytes wide so we need u64 */ -static SENSOR_DEVICE_ATTR(energy1_input, 0444, ltc2947_show_value, NULL, - LTC2947_REG_ENERGY1); -static SENSOR_DEVICE_ATTR(energy2_input, 0444, ltc2947_show_value, NULL, - LTC2947_REG_ENERGY2); - -static struct attribute *ltc2947_attrs[] = { - &sensor_dev_attr_energy1_input.dev_attr.attr, - &sensor_dev_attr_energy2_input.dev_attr.attr, - NULL, -}; -ATTRIBUTE_GROUPS(ltc2947); - -static void ltc2947_clk_disable(void *data) -{ - struct clk *extclk = data; - - clk_disable_unprepare(extclk); -} - static int ltc2947_setup(struct ltc2947_data *st) { int ret; @@ -989,8 +955,12 @@ static int ltc2947_setup(struct ltc2947_data *st) return ret; /* check external clock presence */ - extclk = devm_clk_get(st->dev, NULL); - if (!IS_ERR(extclk)) { + extclk = devm_clk_get_optional_enabled(st->dev, NULL); + if (IS_ERR(extclk)) + return dev_err_probe(st->dev, PTR_ERR(extclk), + "Failed to get external clock\n"); + + if (extclk) { unsigned long rate_hz; u8 pre = 0, div, tbctl; u64 aux; @@ -1003,14 +973,6 @@ static int ltc2947_setup(struct ltc2947_data *st) return -EINVAL; } - ret = clk_prepare_enable(extclk); - if (ret) - return ret; - - ret = devm_add_action_or_reset(st->dev, ltc2947_clk_disable, - extclk); - if (ret) - return ret; /* as in table 1 of the datasheet */ if (rate_hz >= LTC2947_CLK_MIN && rate_hz <= 1000000) pre = 0; @@ -1045,9 +1007,8 @@ static int ltc2947_setup(struct ltc2947_data *st) /* 19.89E-6 * 10E9 */ st->lsb_energy = 19890; } - ret = of_property_read_u32_array(st->dev->of_node, - "adi,accumulator-ctl-pol", accum, - ARRAY_SIZE(accum)); + ret = device_property_read_u32_array(st->dev, "adi,accumulator-ctl-pol", + accum, ARRAY_SIZE(accum)); if (!ret) { u32 accum_reg = LTC2947_ACCUM_POL_1(accum[0]) | LTC2947_ACCUM_POL_2(accum[1]); @@ -1056,9 +1017,9 @@ static int ltc2947_setup(struct ltc2947_data *st) if (ret) return ret; } - ret = of_property_read_u32(st->dev->of_node, - "adi,accumulation-deadband-microamp", - &deadband); + ret = device_property_read_u32(st->dev, + "adi,accumulation-deadband-microamp", + &deadband); if (!ret) { /* the LSB is the same as the current, so 3mA */ ret = regmap_write(st->map, LTC2947_REG_ACCUM_DEADBAND, @@ -1067,7 +1028,7 @@ static int ltc2947_setup(struct ltc2947_data *st) return ret; } /* check gpio cfg */ - ret = of_property_read_u32(st->dev->of_node, "adi,gpio-out-pol", &pol); + ret = device_property_read_u32(st->dev, "adi,gpio-out-pol", &pol); if (!ret) { /* setup GPIO as output */ u32 gpio_ctl = LTC2947_GPIO_EN(1) | LTC2947_GPIO_FAN_EN(1) | @@ -1078,8 +1039,8 @@ static int ltc2947_setup(struct ltc2947_data *st) if (ret) return ret; } - ret = of_property_read_u32_array(st->dev->of_node, "adi,gpio-in-accum", - accum, ARRAY_SIZE(accum)); + ret = device_property_read_u32_array(st->dev, "adi,gpio-in-accum", + accum, ARRAY_SIZE(accum)); if (!ret) { /* * Setup the accum options. The gpioctl is already defined as @@ -1118,20 +1079,18 @@ int ltc2947_core_probe(struct regmap *map, const char *name) st->map = map; st->dev = dev; dev_set_drvdata(dev, st); - mutex_init(&st->lock); ret = ltc2947_setup(st); if (ret) return ret; hwmon = devm_hwmon_device_register_with_info(dev, name, st, - <c2947_chip_info, - ltc2947_groups); + <c2947_chip_info, NULL); return PTR_ERR_OR_ZERO(hwmon); } EXPORT_SYMBOL_GPL(ltc2947_core_probe); -static int __maybe_unused ltc2947_resume(struct device *dev) +static int ltc2947_resume(struct device *dev) { struct ltc2947_data *st = dev_get_drvdata(dev); u32 ctrl = 0; @@ -1160,7 +1119,7 @@ static int __maybe_unused ltc2947_resume(struct device *dev) LTC2947_CONT_MODE_MASK, LTC2947_CONT_MODE(1)); } -static int __maybe_unused ltc2947_suspend(struct device *dev) +static int ltc2947_suspend(struct device *dev) { struct ltc2947_data *st = dev_get_drvdata(dev); @@ -1168,8 +1127,7 @@ static int __maybe_unused ltc2947_suspend(struct device *dev) LTC2947_SHUTDOWN_MASK, 1); } -SIMPLE_DEV_PM_OPS(ltc2947_pm_ops, ltc2947_suspend, ltc2947_resume); -EXPORT_SYMBOL_GPL(ltc2947_pm_ops); +EXPORT_SIMPLE_DEV_PM_OPS(ltc2947_pm_ops, ltc2947_suspend, ltc2947_resume); const struct of_device_id ltc2947_of_match[] = { { .compatible = "adi,ltc2947" }, |
