diff options
-rw-r--r-- | drivers/hwmon/tmp421.c | 133 |
1 files changed, 58 insertions, 75 deletions
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 85d48d80822a..bfb98b96c781 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c | |||
@@ -72,6 +72,10 @@ MODULE_DEVICE_TABLE(i2c, tmp421_id); | |||
72 | struct tmp421_data { | 72 | struct tmp421_data { |
73 | struct i2c_client *client; | 73 | struct i2c_client *client; |
74 | struct mutex update_lock; | 74 | struct mutex update_lock; |
75 | u32 temp_config[5]; | ||
76 | struct hwmon_channel_info temp_info; | ||
77 | const struct hwmon_channel_info *info[2]; | ||
78 | struct hwmon_chip_info chip; | ||
75 | char valid; | 79 | char valid; |
76 | unsigned long last_updated; | 80 | unsigned long last_updated; |
77 | int channels; | 81 | int channels; |
@@ -125,85 +129,46 @@ static struct tmp421_data *tmp421_update_device(struct device *dev) | |||
125 | return data; | 129 | return data; |
126 | } | 130 | } |
127 | 131 | ||
128 | static ssize_t show_temp_value(struct device *dev, | 132 | static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, |
129 | struct device_attribute *devattr, char *buf) | 133 | u32 attr, int channel, long *val) |
130 | { | 134 | { |
131 | int index = to_sensor_dev_attr(devattr)->index; | 135 | struct tmp421_data *tmp421 = tmp421_update_device(dev); |
132 | struct tmp421_data *data = tmp421_update_device(dev); | 136 | |
133 | int temp; | 137 | switch (attr) { |
134 | 138 | case hwmon_temp_input: | |
135 | mutex_lock(&data->update_lock); | 139 | if (tmp421->config & TMP421_CONFIG_RANGE) |
136 | if (data->config & TMP421_CONFIG_RANGE) | 140 | *val = temp_from_u16(tmp421->temp[channel]); |
137 | temp = temp_from_u16(data->temp[index]); | 141 | else |
138 | else | 142 | *val = temp_from_s16(tmp421->temp[channel]); |
139 | temp = temp_from_s16(data->temp[index]); | 143 | return 0; |
140 | mutex_unlock(&data->update_lock); | 144 | case hwmon_temp_fault: |
141 | 145 | /* | |
142 | return sprintf(buf, "%d\n", temp); | 146 | * The OPEN bit signals a fault. This is bit 0 of the temperature |
143 | } | 147 | * register (low byte). |
148 | */ | ||
149 | *val = tmp421->temp[channel] & 0x01; | ||
150 | return 0; | ||
151 | default: | ||
152 | return -EOPNOTSUPP; | ||
153 | } | ||
144 | 154 | ||
145 | static ssize_t show_fault(struct device *dev, | ||
146 | struct device_attribute *devattr, char *buf) | ||
147 | { | ||
148 | int index = to_sensor_dev_attr(devattr)->index; | ||
149 | struct tmp421_data *data = tmp421_update_device(dev); | ||
150 | |||
151 | /* | ||
152 | * The OPEN bit signals a fault. This is bit 0 of the temperature | ||
153 | * register (low byte). | ||
154 | */ | ||
155 | if (data->temp[index] & 0x01) | ||
156 | return sprintf(buf, "1\n"); | ||
157 | else | ||
158 | return sprintf(buf, "0\n"); | ||
159 | } | 155 | } |
160 | 156 | ||
161 | static umode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a, | 157 | static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, |
162 | int n) | 158 | u32 attr, int channel) |
163 | { | 159 | { |
164 | struct device *dev = container_of(kobj, struct device, kobj); | 160 | switch (attr) { |
165 | struct tmp421_data *data = dev_get_drvdata(dev); | 161 | case hwmon_temp_fault: |
166 | struct device_attribute *devattr; | 162 | if (channel == 0) |
167 | unsigned int index; | 163 | return 0; |
168 | 164 | return S_IRUGO; | |
169 | devattr = container_of(a, struct device_attribute, attr); | 165 | case hwmon_temp_input: |
170 | index = to_sensor_dev_attr(devattr)->index; | 166 | return S_IRUGO; |
171 | 167 | default: | |
172 | if (index < data->channels) | 168 | return 0; |
173 | return a->mode; | 169 | } |
174 | |||
175 | return 0; | ||
176 | } | 170 | } |
177 | 171 | ||
178 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0); | ||
179 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1); | ||
180 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1); | ||
181 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2); | ||
182 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2); | ||
183 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3); | ||
184 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3); | ||
185 | |||
186 | static struct attribute *tmp421_attr[] = { | ||
187 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
188 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
189 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
190 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
191 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
192 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
193 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
194 | NULL | ||
195 | }; | ||
196 | |||
197 | static const struct attribute_group tmp421_group = { | ||
198 | .attrs = tmp421_attr, | ||
199 | .is_visible = tmp421_is_visible, | ||
200 | }; | ||
201 | |||
202 | static const struct attribute_group *tmp421_groups[] = { | ||
203 | &tmp421_group, | ||
204 | NULL | ||
205 | }; | ||
206 | |||
207 | static int tmp421_init_client(struct i2c_client *client) | 172 | static int tmp421_init_client(struct i2c_client *client) |
208 | { | 173 | { |
209 | int config, config_orig; | 174 | int config, config_orig; |
@@ -289,13 +254,18 @@ static int tmp421_detect(struct i2c_client *client, | |||
289 | return 0; | 254 | return 0; |
290 | } | 255 | } |
291 | 256 | ||
257 | static const struct hwmon_ops tmp421_ops = { | ||
258 | .is_visible = tmp421_is_visible, | ||
259 | .read = tmp421_read, | ||
260 | }; | ||
261 | |||
292 | static int tmp421_probe(struct i2c_client *client, | 262 | static int tmp421_probe(struct i2c_client *client, |
293 | const struct i2c_device_id *id) | 263 | const struct i2c_device_id *id) |
294 | { | 264 | { |
295 | struct device *dev = &client->dev; | 265 | struct device *dev = &client->dev; |
296 | struct device *hwmon_dev; | 266 | struct device *hwmon_dev; |
297 | struct tmp421_data *data; | 267 | struct tmp421_data *data; |
298 | int err; | 268 | int i, err; |
299 | 269 | ||
300 | data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL); | 270 | data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL); |
301 | if (!data) | 271 | if (!data) |
@@ -309,8 +279,21 @@ static int tmp421_probe(struct i2c_client *client, | |||
309 | if (err) | 279 | if (err) |
310 | return err; | 280 | return err; |
311 | 281 | ||
312 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, | 282 | for (i = 0; i < data->channels; i++) |
313 | data, tmp421_groups); | 283 | data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT; |
284 | |||
285 | data->chip.ops = &tmp421_ops; | ||
286 | data->chip.info = data->info; | ||
287 | |||
288 | data->info[0] = &data->temp_info; | ||
289 | |||
290 | data->temp_info.type = hwmon_temp; | ||
291 | data->temp_info.config = data->temp_config; | ||
292 | |||
293 | hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, | ||
294 | data, | ||
295 | &data->chip, | ||
296 | NULL); | ||
314 | return PTR_ERR_OR_ZERO(hwmon_dev); | 297 | return PTR_ERR_OR_ZERO(hwmon_dev); |
315 | } | 298 | } |
316 | 299 | ||