| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* Hwmon client for industrial I/O devices |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (c) 2011 Jonathan Cameron |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 6 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 7 | | - * the Free Software Foundation. |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | 7 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 47 | 44 | int ret; |
|---|
| 48 | 45 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); |
|---|
| 49 | 46 | struct iio_hwmon_state *state = dev_get_drvdata(dev); |
|---|
| 47 | + struct iio_channel *chan = &state->channels[sattr->index]; |
|---|
| 48 | + enum iio_chan_type type; |
|---|
| 50 | 49 | |
|---|
| 51 | | - ret = iio_read_channel_processed(&state->channels[sattr->index], |
|---|
| 52 | | - &result); |
|---|
| 50 | + ret = iio_read_channel_processed(chan, &result); |
|---|
| 53 | 51 | if (ret < 0) |
|---|
| 54 | 52 | return ret; |
|---|
| 53 | + |
|---|
| 54 | + ret = iio_get_channel_type(chan, &type); |
|---|
| 55 | + if (ret < 0) |
|---|
| 56 | + return ret; |
|---|
| 57 | + |
|---|
| 58 | + if (type == IIO_POWER) |
|---|
| 59 | + result *= 1000; /* mili-Watts to micro-Watts conversion */ |
|---|
| 55 | 60 | |
|---|
| 56 | 61 | return sprintf(buf, "%d\n", result); |
|---|
| 57 | 62 | } |
|---|
| .. | .. |
|---|
| 62 | 67 | struct iio_hwmon_state *st; |
|---|
| 63 | 68 | struct sensor_device_attribute *a; |
|---|
| 64 | 69 | int ret, i; |
|---|
| 65 | | - int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1; |
|---|
| 70 | + int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1, power_i = 1; |
|---|
| 66 | 71 | enum iio_chan_type type; |
|---|
| 67 | 72 | struct iio_channel *channels; |
|---|
| 68 | | - const char *name = "iio_hwmon"; |
|---|
| 69 | 73 | struct device *hwmon_dev; |
|---|
| 70 | 74 | char *sname; |
|---|
| 71 | | - |
|---|
| 72 | | - if (dev->of_node && dev->of_node->name) |
|---|
| 73 | | - name = dev->of_node->name; |
|---|
| 74 | 75 | |
|---|
| 75 | 76 | channels = devm_iio_channel_get_all(dev); |
|---|
| 76 | 77 | if (IS_ERR(channels)) { |
|---|
| .. | .. |
|---|
| 96 | 97 | return -ENOMEM; |
|---|
| 97 | 98 | |
|---|
| 98 | 99 | for (i = 0; i < st->num_channels; i++) { |
|---|
| 100 | + const char *prefix; |
|---|
| 101 | + int n; |
|---|
| 102 | + |
|---|
| 99 | 103 | a = devm_kzalloc(dev, sizeof(*a), GFP_KERNEL); |
|---|
| 100 | 104 | if (a == NULL) |
|---|
| 101 | 105 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 107 | 111 | |
|---|
| 108 | 112 | switch (type) { |
|---|
| 109 | 113 | case IIO_VOLTAGE: |
|---|
| 110 | | - a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
|---|
| 111 | | - "in%d_input", |
|---|
| 112 | | - in_i++); |
|---|
| 114 | + n = in_i++; |
|---|
| 115 | + prefix = "in"; |
|---|
| 113 | 116 | break; |
|---|
| 114 | 117 | case IIO_TEMP: |
|---|
| 115 | | - a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
|---|
| 116 | | - "temp%d_input", |
|---|
| 117 | | - temp_i++); |
|---|
| 118 | + n = temp_i++; |
|---|
| 119 | + prefix = "temp"; |
|---|
| 118 | 120 | break; |
|---|
| 119 | 121 | case IIO_CURRENT: |
|---|
| 120 | | - a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
|---|
| 121 | | - "curr%d_input", |
|---|
| 122 | | - curr_i++); |
|---|
| 122 | + n = curr_i++; |
|---|
| 123 | + prefix = "curr"; |
|---|
| 124 | + break; |
|---|
| 125 | + case IIO_POWER: |
|---|
| 126 | + n = power_i++; |
|---|
| 127 | + prefix = "power"; |
|---|
| 123 | 128 | break; |
|---|
| 124 | 129 | case IIO_HUMIDITYRELATIVE: |
|---|
| 125 | | - a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
|---|
| 126 | | - "humidity%d_input", |
|---|
| 127 | | - humidity_i++); |
|---|
| 130 | + n = humidity_i++; |
|---|
| 131 | + prefix = "humidity"; |
|---|
| 128 | 132 | break; |
|---|
| 129 | 133 | default: |
|---|
| 130 | 134 | return -EINVAL; |
|---|
| 131 | 135 | } |
|---|
| 136 | + |
|---|
| 137 | + a->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, |
|---|
| 138 | + "%s%d_input", |
|---|
| 139 | + prefix, n); |
|---|
| 132 | 140 | if (a->dev_attr.attr.name == NULL) |
|---|
| 133 | 141 | return -ENOMEM; |
|---|
| 134 | 142 | |
|---|
| 135 | 143 | a->dev_attr.show = iio_hwmon_read_val; |
|---|
| 136 | | - a->dev_attr.attr.mode = S_IRUGO; |
|---|
| 144 | + a->dev_attr.attr.mode = 0444; |
|---|
| 137 | 145 | a->index = i; |
|---|
| 138 | 146 | st->attrs[i] = &a->dev_attr.attr; |
|---|
| 139 | 147 | } |
|---|
| .. | .. |
|---|
| 141 | 149 | st->attr_group.attrs = st->attrs; |
|---|
| 142 | 150 | st->groups[0] = &st->attr_group; |
|---|
| 143 | 151 | |
|---|
| 144 | | - sname = devm_kstrdup(dev, name, GFP_KERNEL); |
|---|
| 145 | | - if (!sname) |
|---|
| 146 | | - return -ENOMEM; |
|---|
| 152 | + if (dev->of_node) { |
|---|
| 153 | + sname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); |
|---|
| 154 | + if (!sname) |
|---|
| 155 | + return -ENOMEM; |
|---|
| 156 | + strreplace(sname, '-', '_'); |
|---|
| 157 | + } else { |
|---|
| 158 | + sname = "iio_hwmon"; |
|---|
| 159 | + } |
|---|
| 147 | 160 | |
|---|
| 148 | | - strreplace(sname, '-', '_'); |
|---|
| 149 | 161 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, sname, st, |
|---|
| 150 | 162 | st->groups); |
|---|
| 151 | 163 | return PTR_ERR_OR_ZERO(hwmon_dev); |
|---|