diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2013-03-12 06:38:47 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-04-08 00:16:38 -0400 |
commit | 4b5e536b0e948b5c756aa1d57218371c242f768d (patch) | |
tree | 2550bb81ab1b0712f190f030c7cead7fc74e7aa8 | |
parent | 51c2a4871c1b47255ff8d74f0a86b2a0defff319 (diff) |
hwmon: (adt7x10) Add alarm interrupt support
This allows an userspace application to poll() on the alarm files to get
notified in case of a temperature threshold event.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Reviewed-by: Hartmut Knaack <knaack.h@gmx.de>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/hwmon/adt7310.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/adt7410.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/adt7x10.c | 41 | ||||
-rw-r--r-- | drivers/hwmon/adt7x10.h | 4 |
4 files changed, 44 insertions, 9 deletions
diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c index f8ea6292bc74..b70a481bca17 100644 --- a/drivers/hwmon/adt7310.c +++ b/drivers/hwmon/adt7310.c | |||
@@ -90,13 +90,13 @@ static const struct adt7x10_ops adt7310_spi_ops = { | |||
90 | 90 | ||
91 | static int adt7310_spi_probe(struct spi_device *spi) | 91 | static int adt7310_spi_probe(struct spi_device *spi) |
92 | { | 92 | { |
93 | return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name, | 93 | return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name, spi->irq, |
94 | &adt7310_spi_ops); | 94 | &adt7310_spi_ops); |
95 | } | 95 | } |
96 | 96 | ||
97 | static int adt7310_spi_remove(struct spi_device *spi) | 97 | static int adt7310_spi_remove(struct spi_device *spi) |
98 | { | 98 | { |
99 | return adt7x10_remove(&spi->dev); | 99 | return adt7x10_remove(&spi->dev, spi->irq); |
100 | } | 100 | } |
101 | 101 | ||
102 | static const struct spi_device_id adt7310_id[] = { | 102 | static const struct spi_device_id adt7310_id[] = { |
diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c index d294445c86dd..0dc066a939b4 100644 --- a/drivers/hwmon/adt7410.c +++ b/drivers/hwmon/adt7410.c | |||
@@ -47,12 +47,12 @@ static int adt7410_i2c_probe(struct i2c_client *client, | |||
47 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) | 47 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) |
48 | return -ENODEV; | 48 | return -ENODEV; |
49 | 49 | ||
50 | return adt7x10_probe(&client->dev, NULL, &adt7410_i2c_ops); | 50 | return adt7x10_probe(&client->dev, NULL, client->irq, &adt7410_i2c_ops); |
51 | } | 51 | } |
52 | 52 | ||
53 | static int adt7410_i2c_remove(struct i2c_client *client) | 53 | static int adt7410_i2c_remove(struct i2c_client *client) |
54 | { | 54 | { |
55 | return adt7x10_remove(&client->dev); | 55 | return adt7x10_remove(&client->dev, client->irq); |
56 | } | 56 | } |
57 | 57 | ||
58 | static const struct i2c_device_id adt7410_ids[] = { | 58 | static const struct i2c_device_id adt7410_ids[] = { |
diff --git a/drivers/hwmon/adt7x10.c b/drivers/hwmon/adt7x10.c index 84b3dfc1c1cd..98141f483165 100644 --- a/drivers/hwmon/adt7x10.c +++ b/drivers/hwmon/adt7x10.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/interrupt.h> | ||
33 | 34 | ||
34 | #include "adt7x10.h" | 35 | #include "adt7x10.h" |
35 | 36 | ||
@@ -112,6 +113,25 @@ static const u8 ADT7X10_REG_TEMP[4] = { | |||
112 | ADT7X10_T_CRIT, /* critical */ | 113 | ADT7X10_T_CRIT, /* critical */ |
113 | }; | 114 | }; |
114 | 115 | ||
116 | static irqreturn_t adt7x10_irq_handler(int irq, void *private) | ||
117 | { | ||
118 | struct device *dev = private; | ||
119 | int status; | ||
120 | |||
121 | status = adt7x10_read_byte(dev, ADT7X10_STATUS); | ||
122 | if (status < 0) | ||
123 | return IRQ_HANDLED; | ||
124 | |||
125 | if (status & ADT7X10_STAT_T_HIGH) | ||
126 | sysfs_notify(&dev->kobj, NULL, "temp1_max_alarm"); | ||
127 | if (status & ADT7X10_STAT_T_LOW) | ||
128 | sysfs_notify(&dev->kobj, NULL, "temp1_min_alarm"); | ||
129 | if (status & ADT7X10_STAT_T_CRIT) | ||
130 | sysfs_notify(&dev->kobj, NULL, "temp1_crit_alarm"); | ||
131 | |||
132 | return IRQ_HANDLED; | ||
133 | } | ||
134 | |||
115 | static int adt7x10_temp_ready(struct device *dev) | 135 | static int adt7x10_temp_ready(struct device *dev) |
116 | { | 136 | { |
117 | int i, status; | 137 | int i, status; |
@@ -359,7 +379,7 @@ static const struct attribute_group adt7x10_group = { | |||
359 | .attrs = adt7x10_attributes, | 379 | .attrs = adt7x10_attributes, |
360 | }; | 380 | }; |
361 | 381 | ||
362 | int adt7x10_probe(struct device *dev, const char *name, | 382 | int adt7x10_probe(struct device *dev, const char *name, int irq, |
363 | const struct adt7x10_ops *ops) | 383 | const struct adt7x10_ops *ops) |
364 | { | 384 | { |
365 | struct adt7x10_data *data; | 385 | struct adt7x10_data *data; |
@@ -387,8 +407,10 @@ int adt7x10_probe(struct device *dev, const char *name, | |||
387 | * Set to 16 bit resolution, continous conversion and comparator mode. | 407 | * Set to 16 bit resolution, continous conversion and comparator mode. |
388 | */ | 408 | */ |
389 | data->config = data->oldconfig; | 409 | data->config = data->oldconfig; |
390 | data->config &= ~ADT7X10_MODE_MASK; | 410 | data->config &= ~(ADT7X10_MODE_MASK | ADT7X10_CT_POLARITY | |
411 | ADT7X10_INT_POLARITY); | ||
391 | data->config |= ADT7X10_FULL | ADT7X10_RESOLUTION | ADT7X10_EVENT_MODE; | 412 | data->config |= ADT7X10_FULL | ADT7X10_RESOLUTION | ADT7X10_EVENT_MODE; |
413 | |||
392 | if (data->config != data->oldconfig) { | 414 | if (data->config != data->oldconfig) { |
393 | ret = adt7x10_write_byte(dev, ADT7X10_CONFIG, data->config); | 415 | ret = adt7x10_write_byte(dev, ADT7X10_CONFIG, data->config); |
394 | if (ret) | 416 | if (ret) |
@@ -422,8 +444,18 @@ int adt7x10_probe(struct device *dev, const char *name, | |||
422 | goto exit_remove_name; | 444 | goto exit_remove_name; |
423 | } | 445 | } |
424 | 446 | ||
447 | if (irq > 0) { | ||
448 | ret = request_threaded_irq(irq, NULL, adt7x10_irq_handler, | ||
449 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
450 | dev_name(dev), dev); | ||
451 | if (ret) | ||
452 | goto exit_hwmon_device_unregister; | ||
453 | } | ||
454 | |||
425 | return 0; | 455 | return 0; |
426 | 456 | ||
457 | exit_hwmon_device_unregister: | ||
458 | hwmon_device_unregister(data->hwmon_dev); | ||
427 | exit_remove_name: | 459 | exit_remove_name: |
428 | if (name) | 460 | if (name) |
429 | device_remove_file(dev, &dev_attr_name); | 461 | device_remove_file(dev, &dev_attr_name); |
@@ -435,10 +467,13 @@ exit_restore: | |||
435 | } | 467 | } |
436 | EXPORT_SYMBOL_GPL(adt7x10_probe); | 468 | EXPORT_SYMBOL_GPL(adt7x10_probe); |
437 | 469 | ||
438 | int adt7x10_remove(struct device *dev) | 470 | int adt7x10_remove(struct device *dev, int irq) |
439 | { | 471 | { |
440 | struct adt7x10_data *data = dev_get_drvdata(dev); | 472 | struct adt7x10_data *data = dev_get_drvdata(dev); |
441 | 473 | ||
474 | if (irq > 0) | ||
475 | free_irq(irq, dev); | ||
476 | |||
442 | hwmon_device_unregister(data->hwmon_dev); | 477 | hwmon_device_unregister(data->hwmon_dev); |
443 | if (data->name) | 478 | if (data->name) |
444 | device_remove_file(dev, &dev_attr_name); | 479 | device_remove_file(dev, &dev_attr_name); |
diff --git a/drivers/hwmon/adt7x10.h b/drivers/hwmon/adt7x10.h index 803d9b91c5db..d491c698529e 100644 --- a/drivers/hwmon/adt7x10.h +++ b/drivers/hwmon/adt7x10.h | |||
@@ -23,9 +23,9 @@ struct adt7x10_ops { | |||
23 | int (*write_word)(struct device *, u8 reg, u16 data); | 23 | int (*write_word)(struct device *, u8 reg, u16 data); |
24 | }; | 24 | }; |
25 | 25 | ||
26 | int adt7x10_probe(struct device *dev, const char *name, | 26 | int adt7x10_probe(struct device *dev, const char *name, int irq, |
27 | const struct adt7x10_ops *ops); | 27 | const struct adt7x10_ops *ops); |
28 | int adt7x10_remove(struct device *dev); | 28 | int adt7x10_remove(struct device *dev, int irq); |
29 | 29 | ||
30 | #ifdef CONFIG_PM_SLEEP | 30 | #ifdef CONFIG_PM_SLEEP |
31 | extern const struct dev_pm_ops adt7x10_dev_pm_ops; | 31 | extern const struct dev_pm_ops adt7x10_dev_pm_ops; |