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 /drivers/hwmon | |
| 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>
Diffstat (limited to 'drivers/hwmon')
| -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; |
