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