linux/drivers/staging/iio/adc/adt7410.c
<<
>>
Prefs
   1/*
   2 * ADT7410 digital temperature sensor driver supporting ADT7410
   3 *
   4 * Copyright 2010 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/device.h>
  11#include <linux/kernel.h>
  12#include <linux/slab.h>
  13#include <linux/sysfs.h>
  14#include <linux/list.h>
  15#include <linux/i2c.h>
  16#include <linux/module.h>
  17
  18#include "../iio.h"
  19#include "../sysfs.h"
  20#include "../events.h"
  21
  22/*
  23 * ADT7410 registers definition
  24 */
  25
  26#define ADT7410_TEMPERATURE             0
  27#define ADT7410_STATUS                  2
  28#define ADT7410_CONFIG                  3
  29#define ADT7410_T_ALARM_HIGH            4
  30#define ADT7410_T_ALARM_LOW             6
  31#define ADT7410_T_CRIT                  8
  32#define ADT7410_T_HYST                  0xA
  33#define ADT7410_ID                      0xB
  34#define ADT7410_RESET                   0x2F
  35
  36/*
  37 * ADT7410 status
  38 */
  39#define ADT7410_STAT_T_LOW              0x10
  40#define ADT7410_STAT_T_HIGH             0x20
  41#define ADT7410_STAT_T_CRIT             0x40
  42#define ADT7410_STAT_NOT_RDY            0x80
  43
  44/*
  45 * ADT7410 config
  46 */
  47#define ADT7410_FAULT_QUEUE_MASK        0x3
  48#define ADT7410_CT_POLARITY             0x4
  49#define ADT7410_INT_POLARITY            0x8
  50#define ADT7410_EVENT_MODE              0x10
  51#define ADT7410_MODE_MASK               0x60
  52#define ADT7410_ONESHOT                 0x20
  53#define ADT7410_SPS                     0x40
  54#define ADT7410_PD                      0x60
  55#define ADT7410_RESOLUTION              0x80
  56
  57/*
  58 * ADT7410 masks
  59 */
  60#define ADT7410_T16_VALUE_SIGN                  0x8000
  61#define ADT7410_T16_VALUE_FLOAT_OFFSET          7
  62#define ADT7410_T16_VALUE_FLOAT_MASK            0x7F
  63#define ADT7410_T13_VALUE_SIGN                  0x1000
  64#define ADT7410_T13_VALUE_OFFSET                3
  65#define ADT7410_T13_VALUE_FLOAT_OFFSET          4
  66#define ADT7410_T13_VALUE_FLOAT_MASK            0xF
  67#define ADT7410_T_HYST_MASK                     0xF
  68#define ADT7410_DEVICE_ID_MASK                  0xF
  69#define ADT7410_MANUFACTORY_ID_MASK             0xF0
  70#define ADT7410_MANUFACTORY_ID_OFFSET           4
  71
  72#define ADT7410_IRQS                            2
  73
  74/*
  75 * struct adt7410_chip_info - chip specifc information
  76 */
  77
  78struct adt7410_chip_info {
  79        struct i2c_client *client;
  80        u8  config;
  81};
  82
  83/*
  84 * adt7410 register access by I2C
  85 */
  86
  87static int adt7410_i2c_read_word(struct adt7410_chip_info *chip, u8 reg, u16 *data)
  88{
  89        struct i2c_client *client = chip->client;
  90        int ret = 0;
  91
  92        ret = i2c_smbus_read_word_data(client, reg);
  93        if (ret < 0) {
  94                dev_err(&client->dev, "I2C read error\n");
  95                return ret;
  96        }
  97
  98        *data = swab16((u16)ret);
  99
 100        return 0;
 101}
 102
 103static int adt7410_i2c_write_word(struct adt7410_chip_info *chip, u8 reg, u16 data)
 104{
 105        struct i2c_client *client = chip->client;
 106        int ret = 0;
 107
 108        ret = i2c_smbus_write_word_data(client, reg, swab16(data));
 109        if (ret < 0)
 110                dev_err(&client->dev, "I2C write error\n");
 111
 112        return ret;
 113}
 114
 115static int adt7410_i2c_read_byte(struct adt7410_chip_info *chip, u8 reg, u8 *data)
 116{
 117        struct i2c_client *client = chip->client;
 118        int ret = 0;
 119
 120        ret = i2c_smbus_read_byte_data(client, reg);
 121        if (ret < 0) {
 122                dev_err(&client->dev, "I2C read error\n");
 123                return ret;
 124        }
 125
 126        *data = (u8)ret;
 127
 128        return 0;
 129}
 130
 131static int adt7410_i2c_write_byte(struct adt7410_chip_info *chip, u8 reg, u8 data)
 132{
 133        struct i2c_client *client = chip->client;
 134        int ret = 0;
 135
 136        ret = i2c_smbus_write_byte_data(client, reg, data);
 137        if (ret < 0)
 138                dev_err(&client->dev, "I2C write error\n");
 139
 140        return ret;
 141}
 142
 143static ssize_t adt7410_show_mode(struct device *dev,
 144                struct device_attribute *attr,
 145                char *buf)
 146{
 147        struct iio_dev *dev_info = dev_get_drvdata(dev);
 148        struct adt7410_chip_info *chip = iio_priv(dev_info);
 149        u8 config;
 150
 151        config = chip->config & ADT7410_MODE_MASK;
 152
 153        switch (config) {
 154        case ADT7410_PD:
 155                return sprintf(buf, "power-down\n");
 156        case ADT7410_ONESHOT:
 157                return sprintf(buf, "one-shot\n");
 158        case ADT7410_SPS:
 159                return sprintf(buf, "sps\n");
 160        default:
 161                return sprintf(buf, "full\n");
 162        }
 163}
 164
 165static ssize_t adt7410_store_mode(struct device *dev,
 166                struct device_attribute *attr,
 167                const char *buf,
 168                size_t len)
 169{
 170        struct iio_dev *dev_info = dev_get_drvdata(dev);
 171        struct adt7410_chip_info *chip = iio_priv(dev_info);
 172        u16 config;
 173        int ret;
 174
 175        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 176        if (ret)
 177                return -EIO;
 178
 179        config = chip->config & (~ADT7410_MODE_MASK);
 180        if (strcmp(buf, "power-down"))
 181                config |= ADT7410_PD;
 182        else if (strcmp(buf, "one-shot"))
 183                config |= ADT7410_ONESHOT;
 184        else if (strcmp(buf, "sps"))
 185                config |= ADT7410_SPS;
 186
 187        ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
 188        if (ret)
 189                return -EIO;
 190
 191        chip->config = config;
 192
 193        return ret;
 194}
 195
 196static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
 197                adt7410_show_mode,
 198                adt7410_store_mode,
 199                0);
 200
 201static ssize_t adt7410_show_available_modes(struct device *dev,
 202                struct device_attribute *attr,
 203                char *buf)
 204{
 205        return sprintf(buf, "full\none-shot\nsps\npower-down\n");
 206}
 207
 208static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7410_show_available_modes, NULL, 0);
 209
 210static ssize_t adt7410_show_resolution(struct device *dev,
 211                struct device_attribute *attr,
 212                char *buf)
 213{
 214        struct iio_dev *dev_info = dev_get_drvdata(dev);
 215        struct adt7410_chip_info *chip = iio_priv(dev_info);
 216        int ret;
 217        int bits;
 218
 219        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 220        if (ret)
 221                return -EIO;
 222
 223        if (chip->config & ADT7410_RESOLUTION)
 224                bits = 16;
 225        else
 226                bits = 13;
 227
 228        return sprintf(buf, "%d bits\n", bits);
 229}
 230
 231static ssize_t adt7410_store_resolution(struct device *dev,
 232                struct device_attribute *attr,
 233                const char *buf,
 234                size_t len)
 235{
 236        struct iio_dev *dev_info = dev_get_drvdata(dev);
 237        struct adt7410_chip_info *chip = iio_priv(dev_info);
 238        unsigned long data;
 239        u16 config;
 240        int ret;
 241
 242        ret = strict_strtoul(buf, 10, &data);
 243        if (ret)
 244                return -EINVAL;
 245
 246        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 247        if (ret)
 248                return -EIO;
 249
 250        config = chip->config & (~ADT7410_RESOLUTION);
 251        if (data)
 252                config |= ADT7410_RESOLUTION;
 253
 254        ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
 255        if (ret)
 256                return -EIO;
 257
 258        chip->config = config;
 259
 260        return ret;
 261}
 262
 263static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR,
 264                adt7410_show_resolution,
 265                adt7410_store_resolution,
 266                0);
 267
 268static ssize_t adt7410_show_id(struct device *dev,
 269                struct device_attribute *attr,
 270                char *buf)
 271{
 272        struct iio_dev *dev_info = dev_get_drvdata(dev);
 273        struct adt7410_chip_info *chip = iio_priv(dev_info);
 274        u8 id;
 275        int ret;
 276
 277        ret = adt7410_i2c_read_byte(chip, ADT7410_ID, &id);
 278        if (ret)
 279                return -EIO;
 280
 281        return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n",
 282                        id & ADT7410_DEVICE_ID_MASK,
 283                        (id & ADT7410_MANUFACTORY_ID_MASK) >> ADT7410_MANUFACTORY_ID_OFFSET);
 284}
 285
 286static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR,
 287                adt7410_show_id,
 288                NULL,
 289                0);
 290
 291static ssize_t adt7410_convert_temperature(struct adt7410_chip_info *chip,
 292                u16 data, char *buf)
 293{
 294        char sign = ' ';
 295
 296        if (chip->config & ADT7410_RESOLUTION) {
 297                if (data & ADT7410_T16_VALUE_SIGN) {
 298                        /* convert supplement to positive value */
 299                        data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data);
 300                        sign = '-';
 301                }
 302                return sprintf(buf, "%c%d.%.7d\n", sign,
 303                                (data >> ADT7410_T16_VALUE_FLOAT_OFFSET),
 304                                (data & ADT7410_T16_VALUE_FLOAT_MASK) * 78125);
 305        } else {
 306                if (data & ADT7410_T13_VALUE_SIGN) {
 307                        /* convert supplement to positive value */
 308                        data >>= ADT7410_T13_VALUE_OFFSET;
 309                        data = (ADT7410_T13_VALUE_SIGN << 1) - data;
 310                        sign = '-';
 311                }
 312                return sprintf(buf, "%c%d.%.4d\n", sign,
 313                                (data >> ADT7410_T13_VALUE_FLOAT_OFFSET),
 314                                (data & ADT7410_T13_VALUE_FLOAT_MASK) * 625);
 315        }
 316}
 317
 318static ssize_t adt7410_show_value(struct device *dev,
 319                struct device_attribute *attr,
 320                char *buf)
 321{
 322        struct iio_dev *dev_info = dev_get_drvdata(dev);
 323        struct adt7410_chip_info *chip = iio_priv(dev_info);
 324        u8 status;
 325        u16 data;
 326        int ret, i = 0;
 327
 328        do {
 329                ret = adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status);
 330                if (ret)
 331                        return -EIO;
 332                i++;
 333                if (i == 10000)
 334                        return -EIO;
 335        } while (status & ADT7410_STAT_NOT_RDY);
 336
 337        ret = adt7410_i2c_read_word(chip, ADT7410_TEMPERATURE, &data);
 338        if (ret)
 339                return -EIO;
 340
 341        return adt7410_convert_temperature(chip, data, buf);
 342}
 343
 344static IIO_DEVICE_ATTR(value, S_IRUGO, adt7410_show_value, NULL, 0);
 345
 346static struct attribute *adt7410_attributes[] = {
 347        &iio_dev_attr_available_modes.dev_attr.attr,
 348        &iio_dev_attr_mode.dev_attr.attr,
 349        &iio_dev_attr_resolution.dev_attr.attr,
 350        &iio_dev_attr_id.dev_attr.attr,
 351        &iio_dev_attr_value.dev_attr.attr,
 352        NULL,
 353};
 354
 355static const struct attribute_group adt7410_attribute_group = {
 356        .attrs = adt7410_attributes,
 357};
 358
 359static irqreturn_t adt7410_event_handler(int irq, void *private)
 360{
 361        struct iio_dev *indio_dev = private;
 362        struct adt7410_chip_info *chip = iio_priv(indio_dev);
 363        s64 timestamp = iio_get_time_ns();
 364        u8 status;
 365
 366        if (adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status))
 367                return IRQ_HANDLED;
 368
 369        if (status & ADT7410_STAT_T_HIGH)
 370                iio_push_event(indio_dev,
 371                               IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
 372                                                    IIO_EV_TYPE_THRESH,
 373                                                    IIO_EV_DIR_RISING),
 374                               timestamp);
 375        if (status & ADT7410_STAT_T_LOW)
 376                iio_push_event(indio_dev,
 377                               IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
 378                                                    IIO_EV_TYPE_THRESH,
 379                                                    IIO_EV_DIR_FALLING),
 380                               timestamp);
 381        if (status & ADT7410_STAT_T_CRIT)
 382                iio_push_event(indio_dev,
 383                               IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
 384                                                    IIO_EV_TYPE_THRESH,
 385                                                    IIO_EV_DIR_RISING),
 386                               timestamp);
 387
 388        return IRQ_HANDLED;
 389}
 390
 391static ssize_t adt7410_show_event_mode(struct device *dev,
 392                struct device_attribute *attr,
 393                char *buf)
 394{
 395        struct iio_dev *dev_info = dev_get_drvdata(dev);
 396        struct adt7410_chip_info *chip = iio_priv(dev_info);
 397        int ret;
 398
 399        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 400        if (ret)
 401                return -EIO;
 402
 403        if (chip->config & ADT7410_EVENT_MODE)
 404                return sprintf(buf, "interrupt\n");
 405        else
 406                return sprintf(buf, "comparator\n");
 407}
 408
 409static ssize_t adt7410_set_event_mode(struct device *dev,
 410                struct device_attribute *attr,
 411                const char *buf,
 412                size_t len)
 413{
 414        struct iio_dev *dev_info = dev_get_drvdata(dev);
 415        struct adt7410_chip_info *chip = iio_priv(dev_info);
 416        u16 config;
 417        int ret;
 418
 419        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 420        if (ret)
 421                return -EIO;
 422
 423        config = chip->config &= ~ADT7410_EVENT_MODE;
 424        if (strcmp(buf, "comparator") != 0)
 425                config |= ADT7410_EVENT_MODE;
 426
 427        ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
 428        if (ret)
 429                return -EIO;
 430
 431        chip->config = config;
 432
 433        return ret;
 434}
 435
 436static ssize_t adt7410_show_available_event_modes(struct device *dev,
 437                struct device_attribute *attr,
 438                char *buf)
 439{
 440        return sprintf(buf, "comparator\ninterrupt\n");
 441}
 442
 443static ssize_t adt7410_show_fault_queue(struct device *dev,
 444                struct device_attribute *attr,
 445                char *buf)
 446{
 447        struct iio_dev *dev_info = dev_get_drvdata(dev);
 448        struct adt7410_chip_info *chip = iio_priv(dev_info);
 449        int ret;
 450
 451        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 452        if (ret)
 453                return -EIO;
 454
 455        return sprintf(buf, "%d\n", chip->config & ADT7410_FAULT_QUEUE_MASK);
 456}
 457
 458static ssize_t adt7410_set_fault_queue(struct device *dev,
 459                struct device_attribute *attr,
 460                const char *buf,
 461                size_t len)
 462{
 463        struct iio_dev *dev_info = dev_get_drvdata(dev);
 464        struct adt7410_chip_info *chip = iio_priv(dev_info);
 465        unsigned long data;
 466        int ret;
 467        u8 config;
 468
 469        ret = strict_strtoul(buf, 10, &data);
 470        if (ret || data > 3)
 471                return -EINVAL;
 472
 473        ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 474        if (ret)
 475                return -EIO;
 476
 477        config = chip->config & ~ADT7410_FAULT_QUEUE_MASK;
 478        config |= data;
 479        ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config);
 480        if (ret)
 481                return -EIO;
 482
 483        chip->config = config;
 484
 485        return ret;
 486}
 487
 488static inline ssize_t adt7410_show_t_bound(struct device *dev,
 489                struct device_attribute *attr,
 490                u8 bound_reg,
 491                char *buf)
 492{
 493        struct iio_dev *dev_info = dev_get_drvdata(dev);
 494        struct adt7410_chip_info *chip = iio_priv(dev_info);
 495        u16 data;
 496        int ret;
 497
 498        ret = adt7410_i2c_read_word(chip, bound_reg, &data);
 499        if (ret)
 500                return -EIO;
 501
 502        return adt7410_convert_temperature(chip, data, buf);
 503}
 504
 505static inline ssize_t adt7410_set_t_bound(struct device *dev,
 506                struct device_attribute *attr,
 507                u8 bound_reg,
 508                const char *buf,
 509                size_t len)
 510{
 511        struct iio_dev *dev_info = dev_get_drvdata(dev);
 512        struct adt7410_chip_info *chip = iio_priv(dev_info);
 513        long tmp1, tmp2;
 514        u16 data;
 515        char *pos;
 516        int ret;
 517
 518        pos = strchr(buf, '.');
 519
 520        ret = strict_strtol(buf, 10, &tmp1);
 521
 522        if (ret || tmp1 > 127 || tmp1 < -128)
 523                return -EINVAL;
 524
 525        if (pos) {
 526                len = strlen(pos);
 527
 528                if (chip->config & ADT7410_RESOLUTION) {
 529                        if (len > ADT7410_T16_VALUE_FLOAT_OFFSET)
 530                                len = ADT7410_T16_VALUE_FLOAT_OFFSET;
 531                        pos[len] = 0;
 532                        ret = strict_strtol(pos, 10, &tmp2);
 533
 534                        if (!ret)
 535                                tmp2 = (tmp2 / 78125) * 78125;
 536                } else {
 537                        if (len > ADT7410_T13_VALUE_FLOAT_OFFSET)
 538                                len = ADT7410_T13_VALUE_FLOAT_OFFSET;
 539                        pos[len] = 0;
 540                        ret = strict_strtol(pos, 10, &tmp2);
 541
 542                        if (!ret)
 543                                tmp2 = (tmp2 / 625) * 625;
 544                }
 545        }
 546
 547        if (tmp1 < 0)
 548                data = (u16)(-tmp1);
 549        else
 550                data = (u16)tmp1;
 551
 552        if (chip->config & ADT7410_RESOLUTION) {
 553                data = (data << ADT7410_T16_VALUE_FLOAT_OFFSET) |
 554                        (tmp2 & ADT7410_T16_VALUE_FLOAT_MASK);
 555
 556                if (tmp1 < 0)
 557                        /* convert positive value to supplyment */
 558                        data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data);
 559        } else {
 560                data = (data << ADT7410_T13_VALUE_FLOAT_OFFSET) |
 561                        (tmp2 & ADT7410_T13_VALUE_FLOAT_MASK);
 562
 563                if (tmp1 < 0)
 564                        /* convert positive value to supplyment */
 565                        data = (ADT7410_T13_VALUE_SIGN << 1) - data;
 566                data <<= ADT7410_T13_VALUE_OFFSET;
 567        }
 568
 569        ret = adt7410_i2c_write_word(chip, bound_reg, data);
 570        if (ret)
 571                return -EIO;
 572
 573        return ret;
 574}
 575
 576static ssize_t adt7410_show_t_alarm_high(struct device *dev,
 577                struct device_attribute *attr,
 578                char *buf)
 579{
 580        return adt7410_show_t_bound(dev, attr,
 581                        ADT7410_T_ALARM_HIGH, buf);
 582}
 583
 584static inline ssize_t adt7410_set_t_alarm_high(struct device *dev,
 585                struct device_attribute *attr,
 586                const char *buf,
 587                size_t len)
 588{
 589        return adt7410_set_t_bound(dev, attr,
 590                        ADT7410_T_ALARM_HIGH, buf, len);
 591}
 592
 593static ssize_t adt7410_show_t_alarm_low(struct device *dev,
 594                struct device_attribute *attr,
 595                char *buf)
 596{
 597        return adt7410_show_t_bound(dev, attr,
 598                        ADT7410_T_ALARM_LOW, buf);
 599}
 600
 601static inline ssize_t adt7410_set_t_alarm_low(struct device *dev,
 602                struct device_attribute *attr,
 603                const char *buf,
 604                size_t len)
 605{
 606        return adt7410_set_t_bound(dev, attr,
 607                        ADT7410_T_ALARM_LOW, buf, len);
 608}
 609
 610static ssize_t adt7410_show_t_crit(struct device *dev,
 611                struct device_attribute *attr,
 612                char *buf)
 613{
 614        return adt7410_show_t_bound(dev, attr,
 615                        ADT7410_T_CRIT, buf);
 616}
 617
 618static inline ssize_t adt7410_set_t_crit(struct device *dev,
 619                struct device_attribute *attr,
 620                const char *buf,
 621                size_t len)
 622{
 623        return adt7410_set_t_bound(dev, attr,
 624                        ADT7410_T_CRIT, buf, len);
 625}
 626
 627static ssize_t adt7410_show_t_hyst(struct device *dev,
 628                struct device_attribute *attr,
 629                char *buf)
 630{
 631        struct iio_dev *dev_info = dev_get_drvdata(dev);
 632        struct adt7410_chip_info *chip = iio_priv(dev_info);
 633        int ret;
 634        u8 t_hyst;
 635
 636        ret = adt7410_i2c_read_byte(chip, ADT7410_T_HYST, &t_hyst);
 637        if (ret)
 638                return -EIO;
 639
 640        return sprintf(buf, "%d\n", t_hyst & ADT7410_T_HYST_MASK);
 641}
 642
 643static inline ssize_t adt7410_set_t_hyst(struct device *dev,
 644                struct device_attribute *attr,
 645                const char *buf,
 646                size_t len)
 647{
 648        struct iio_dev *dev_info = dev_get_drvdata(dev);
 649        struct adt7410_chip_info *chip = iio_priv(dev_info);
 650        int ret;
 651        unsigned long data;
 652        u8 t_hyst;
 653
 654        ret = strict_strtol(buf, 10, &data);
 655
 656        if (ret || data > ADT7410_T_HYST_MASK)
 657                return -EINVAL;
 658
 659        t_hyst = (u8)data;
 660
 661        ret = adt7410_i2c_write_byte(chip, ADT7410_T_HYST, t_hyst);
 662        if (ret)
 663                return -EIO;
 664
 665        return ret;
 666}
 667
 668static IIO_DEVICE_ATTR(event_mode,
 669                       S_IRUGO | S_IWUSR,
 670                       adt7410_show_event_mode, adt7410_set_event_mode, 0);
 671static IIO_DEVICE_ATTR(available_event_modes,
 672                       S_IRUGO,
 673                       adt7410_show_available_event_modes, NULL, 0);
 674static IIO_DEVICE_ATTR(fault_queue,
 675                       S_IRUGO | S_IWUSR,
 676                       adt7410_show_fault_queue, adt7410_set_fault_queue, 0);
 677static IIO_DEVICE_ATTR(t_alarm_high,
 678                       S_IRUGO | S_IWUSR,
 679                       adt7410_show_t_alarm_high, adt7410_set_t_alarm_high, 0);
 680static IIO_DEVICE_ATTR(t_alarm_low,
 681                       S_IRUGO | S_IWUSR,
 682                       adt7410_show_t_alarm_low, adt7410_set_t_alarm_low, 0);
 683static IIO_DEVICE_ATTR(t_crit,
 684                       S_IRUGO | S_IWUSR,
 685                       adt7410_show_t_crit, adt7410_set_t_crit, 0);
 686static IIO_DEVICE_ATTR(t_hyst,
 687                       S_IRUGO | S_IWUSR,
 688                       adt7410_show_t_hyst, adt7410_set_t_hyst, 0);
 689
 690static struct attribute *adt7410_event_int_attributes[] = {
 691        &iio_dev_attr_event_mode.dev_attr.attr,
 692        &iio_dev_attr_available_event_modes.dev_attr.attr,
 693        &iio_dev_attr_fault_queue.dev_attr.attr,
 694        &iio_dev_attr_t_alarm_high.dev_attr.attr,
 695        &iio_dev_attr_t_alarm_low.dev_attr.attr,
 696        &iio_dev_attr_t_hyst.dev_attr.attr,
 697        NULL,
 698};
 699
 700static struct attribute *adt7410_event_ct_attributes[] = {
 701        &iio_dev_attr_event_mode.dev_attr.attr,
 702        &iio_dev_attr_available_event_modes.dev_attr.attr,
 703        &iio_dev_attr_fault_queue.dev_attr.attr,
 704        &iio_dev_attr_t_crit.dev_attr.attr,
 705        &iio_dev_attr_t_hyst.dev_attr.attr,
 706        NULL,
 707};
 708
 709static struct attribute_group adt7410_event_attribute_group[ADT7410_IRQS] = {
 710        {
 711                .attrs = adt7410_event_int_attributes,
 712                .name = "events",
 713        }, {
 714                .attrs = adt7410_event_ct_attributes,
 715                .name = "events",
 716        }
 717};
 718
 719static const struct iio_info adt7410_info = {
 720        .attrs = &adt7410_attribute_group,
 721        .event_attrs = adt7410_event_attribute_group,
 722        .driver_module = THIS_MODULE,
 723};
 724
 725/*
 726 * device probe and remove
 727 */
 728
 729static int __devinit adt7410_probe(struct i2c_client *client,
 730                const struct i2c_device_id *id)
 731{
 732        struct adt7410_chip_info *chip;
 733        struct iio_dev *indio_dev;
 734        int ret = 0;
 735        unsigned long *adt7410_platform_data = client->dev.platform_data;
 736
 737        indio_dev = iio_allocate_device(sizeof(*chip));
 738        if (indio_dev == NULL) {
 739                ret = -ENOMEM;
 740                goto error_ret;
 741        }
 742        chip = iio_priv(indio_dev);
 743        /* this is only used for device removal purposes */
 744        i2c_set_clientdata(client, indio_dev);
 745
 746        chip->client = client;
 747
 748        indio_dev->name = id->name;
 749        indio_dev->dev.parent = &client->dev;
 750        indio_dev->info = &adt7410_info;
 751        indio_dev->modes = INDIO_DIRECT_MODE;
 752
 753        /* CT critcal temperature event. line 0 */
 754        if (client->irq) {
 755                ret = request_threaded_irq(client->irq,
 756                                           NULL,
 757                                           &adt7410_event_handler,
 758                                           IRQF_TRIGGER_LOW,
 759                                           id->name,
 760                                           indio_dev);
 761                if (ret)
 762                        goto error_free_dev;
 763        }
 764
 765        /* INT bound temperature alarm event. line 1 */
 766        if (adt7410_platform_data[0]) {
 767                ret = request_threaded_irq(adt7410_platform_data[0],
 768                                           NULL,
 769                                           &adt7410_event_handler,
 770                                           adt7410_platform_data[1],
 771                                           id->name,
 772                                           indio_dev);
 773                if (ret)
 774                        goto error_unreg_ct_irq;
 775        }
 776
 777        if (client->irq && adt7410_platform_data[0]) {
 778
 779                ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config);
 780                if (ret) {
 781                        ret = -EIO;
 782                        goto error_unreg_int_irq;
 783                }
 784
 785                /* set irq polarity low level */
 786                chip->config &= ~ADT7410_CT_POLARITY;
 787
 788                if (adt7410_platform_data[1] & IRQF_TRIGGER_HIGH)
 789                        chip->config |= ADT7410_INT_POLARITY;
 790                else
 791                        chip->config &= ~ADT7410_INT_POLARITY;
 792
 793                ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, chip->config);
 794                if (ret) {
 795                        ret = -EIO;
 796                        goto error_unreg_int_irq;
 797                }
 798        }
 799        ret = iio_device_register(indio_dev);
 800        if (ret)
 801                goto error_unreg_int_irq;
 802
 803        dev_info(&client->dev, "%s temperature sensor registered.\n",
 804                         id->name);
 805
 806        return 0;
 807
 808error_unreg_int_irq:
 809        free_irq(adt7410_platform_data[0], indio_dev);
 810error_unreg_ct_irq:
 811        free_irq(client->irq, indio_dev);
 812error_free_dev:
 813        iio_free_device(indio_dev);
 814error_ret:
 815        return ret;
 816}
 817
 818static int __devexit adt7410_remove(struct i2c_client *client)
 819{
 820        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 821        unsigned long *adt7410_platform_data = client->dev.platform_data;
 822
 823        iio_device_unregister(indio_dev);
 824        if (adt7410_platform_data[0])
 825                free_irq(adt7410_platform_data[0], indio_dev);
 826        if (client->irq)
 827                free_irq(client->irq, indio_dev);
 828        iio_free_device(indio_dev);
 829
 830        return 0;
 831}
 832
 833static const struct i2c_device_id adt7410_id[] = {
 834        { "adt7410", 0 },
 835        {}
 836};
 837
 838MODULE_DEVICE_TABLE(i2c, adt7410_id);
 839
 840static struct i2c_driver adt7410_driver = {
 841        .driver = {
 842                .name = "adt7410",
 843        },
 844        .probe = adt7410_probe,
 845        .remove = __devexit_p(adt7410_remove),
 846        .id_table = adt7410_id,
 847};
 848module_i2c_driver(adt7410_driver);
 849
 850MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
 851MODULE_DESCRIPTION("Analog Devices ADT7410 digital"
 852                        " temperature sensor driver");
 853MODULE_LICENSE("GPL v2");
 854