linux/drivers/staging/iio/adc/ad7314.c
<<
>>
Prefs
   1/*
   2 * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302
   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/spi/spi.h>
  18#include <linux/rtc.h>
  19
  20#include "../iio.h"
  21#include "../sysfs.h"
  22
  23/*
  24 * AD7314 power mode
  25 */
  26#define AD7314_PD               0x2000
  27
  28/*
  29 * AD7314 temperature masks
  30 */
  31#define AD7314_TEMP_SIGN                0x200
  32#define AD7314_TEMP_MASK                0x7FE0
  33#define AD7314_TEMP_OFFSET              5
  34#define AD7314_TEMP_FLOAT_OFFSET        2
  35#define AD7314_TEMP_FLOAT_MASK          0x3
  36
  37/*
  38 * ADT7301 and ADT7302 temperature masks
  39 */
  40#define ADT7301_TEMP_SIGN               0x2000
  41#define ADT7301_TEMP_MASK               0x2FFF
  42#define ADT7301_TEMP_FLOAT_OFFSET       5
  43#define ADT7301_TEMP_FLOAT_MASK         0x1F
  44
  45/*
  46 * struct ad7314_chip_info - chip specifc information
  47 */
  48
  49struct ad7314_chip_info {
  50        const char *name;
  51        struct spi_device *spi_dev;
  52        struct iio_dev *indio_dev;
  53        s64 last_timestamp;
  54        u8  mode;
  55};
  56
  57/*
  58 * ad7314 register access by SPI
  59 */
  60
  61static int ad7314_spi_read(struct ad7314_chip_info *chip, u16 *data)
  62{
  63        struct spi_device *spi_dev = chip->spi_dev;
  64        int ret = 0;
  65        u16 value;
  66
  67        ret = spi_read(spi_dev, (u8 *)&value, sizeof(value));
  68        if (ret < 0) {
  69                dev_err(&spi_dev->dev, "SPI read error\n");
  70                return ret;
  71        }
  72
  73        *data = be16_to_cpu((u16)value);
  74
  75        return ret;
  76}
  77
  78static int ad7314_spi_write(struct ad7314_chip_info *chip, u16 data)
  79{
  80        struct spi_device *spi_dev = chip->spi_dev;
  81        int ret = 0;
  82        u16 value = cpu_to_be16(data);
  83
  84        ret = spi_write(spi_dev, (u8 *)&value, sizeof(value));
  85        if (ret < 0)
  86                dev_err(&spi_dev->dev, "SPI write error\n");
  87
  88        return ret;
  89}
  90
  91static ssize_t ad7314_show_mode(struct device *dev,
  92                struct device_attribute *attr,
  93                char *buf)
  94{
  95        struct iio_dev *dev_info = dev_get_drvdata(dev);
  96        struct ad7314_chip_info *chip = dev_info->dev_data;
  97
  98        if (chip->mode)
  99                return sprintf(buf, "power-save\n");
 100        else
 101                return sprintf(buf, "full\n");
 102}
 103
 104static ssize_t ad7314_store_mode(struct device *dev,
 105                struct device_attribute *attr,
 106                const char *buf,
 107                size_t len)
 108{
 109        struct iio_dev *dev_info = dev_get_drvdata(dev);
 110        struct ad7314_chip_info *chip = dev_info->dev_data;
 111        u16 mode = 0;
 112        int ret;
 113
 114        if (!strcmp(buf, "full"))
 115                mode = AD7314_PD;
 116
 117        ret = ad7314_spi_write(chip, mode);
 118        if (ret)
 119                return -EIO;
 120
 121        chip->mode = mode;
 122
 123        return len;
 124}
 125
 126static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
 127                ad7314_show_mode,
 128                ad7314_store_mode,
 129                0);
 130
 131static ssize_t ad7314_show_available_modes(struct device *dev,
 132                struct device_attribute *attr,
 133                char *buf)
 134{
 135        return sprintf(buf, "full\npower-save\n");
 136}
 137
 138static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7314_show_available_modes, NULL, 0);
 139
 140static ssize_t ad7314_show_temperature(struct device *dev,
 141                struct device_attribute *attr,
 142                char *buf)
 143{
 144        struct iio_dev *dev_info = dev_get_drvdata(dev);
 145        struct ad7314_chip_info *chip = dev_info->dev_data;
 146        u16 data;
 147        char sign = ' ';
 148        int ret;
 149
 150        if (chip->mode) {
 151                ret = ad7314_spi_write(chip, 0);
 152                if (ret)
 153                        return -EIO;
 154        }
 155
 156        ret = ad7314_spi_read(chip, &data);
 157        if (ret)
 158                return -EIO;
 159
 160        if (chip->mode)
 161                ad7314_spi_write(chip, chip->mode);
 162
 163        if (strcmp(chip->name, "ad7314")) {
 164                data = (data & AD7314_TEMP_MASK) >>
 165                        AD7314_TEMP_OFFSET;
 166                if (data & AD7314_TEMP_SIGN) {
 167                        data = (AD7314_TEMP_SIGN << 1) - data;
 168                        sign = '-';
 169                }
 170
 171                return sprintf(buf, "%c%d.%.2d\n", sign,
 172                                data >> AD7314_TEMP_FLOAT_OFFSET,
 173                                (data & AD7314_TEMP_FLOAT_MASK) * 25);
 174        } else {
 175                data &= ADT7301_TEMP_MASK;
 176                if (data & ADT7301_TEMP_SIGN) {
 177                        data = (ADT7301_TEMP_SIGN << 1) - data;
 178                        sign = '-';
 179                }
 180
 181                return sprintf(buf, "%c%d.%.5d\n", sign,
 182                                data >> ADT7301_TEMP_FLOAT_OFFSET,
 183                                (data & ADT7301_TEMP_FLOAT_MASK) * 3125);
 184        }
 185}
 186
 187static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0);
 188
 189static ssize_t ad7314_show_name(struct device *dev,
 190                struct device_attribute *attr,
 191                char *buf)
 192{
 193        struct iio_dev *dev_info = dev_get_drvdata(dev);
 194        struct ad7314_chip_info *chip = dev_info->dev_data;
 195        return sprintf(buf, "%s\n", chip->name);
 196}
 197
 198static IIO_DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL, 0);
 199
 200static struct attribute *ad7314_attributes[] = {
 201        &iio_dev_attr_available_modes.dev_attr.attr,
 202        &iio_dev_attr_mode.dev_attr.attr,
 203        &iio_dev_attr_temperature.dev_attr.attr,
 204        &iio_dev_attr_name.dev_attr.attr,
 205        NULL,
 206};
 207
 208static const struct attribute_group ad7314_attribute_group = {
 209        .attrs = ad7314_attributes,
 210};
 211
 212/*
 213 * device probe and remove
 214 */
 215
 216static int __devinit ad7314_probe(struct spi_device *spi_dev)
 217{
 218        struct ad7314_chip_info *chip;
 219        int ret = 0;
 220
 221        chip = kzalloc(sizeof(struct ad7314_chip_info), GFP_KERNEL);
 222
 223        if (chip == NULL)
 224                return -ENOMEM;
 225
 226        /* this is only used for device removal purposes */
 227        dev_set_drvdata(&spi_dev->dev, chip);
 228
 229        chip->spi_dev = spi_dev;
 230        chip->name = spi_dev->modalias;
 231
 232        chip->indio_dev = iio_allocate_device();
 233        if (chip->indio_dev == NULL) {
 234                ret = -ENOMEM;
 235                goto error_free_chip;
 236        }
 237
 238        chip->indio_dev->dev.parent = &spi_dev->dev;
 239        chip->indio_dev->attrs = &ad7314_attribute_group;
 240        chip->indio_dev->dev_data = (void *)chip;
 241        chip->indio_dev->driver_module = THIS_MODULE;
 242
 243        ret = iio_device_register(chip->indio_dev);
 244        if (ret)
 245                goto error_free_dev;
 246
 247        dev_info(&spi_dev->dev, "%s temperature sensor registered.\n",
 248                         chip->name);
 249
 250        return 0;
 251error_free_dev:
 252        iio_free_device(chip->indio_dev);
 253error_free_chip:
 254        kfree(chip);
 255
 256        return ret;
 257}
 258
 259static int __devexit ad7314_remove(struct spi_device *spi_dev)
 260{
 261        struct ad7314_chip_info *chip = dev_get_drvdata(&spi_dev->dev);
 262        struct iio_dev *indio_dev = chip->indio_dev;
 263
 264        dev_set_drvdata(&spi_dev->dev, NULL);
 265        if (spi_dev->irq)
 266                iio_unregister_interrupt_line(indio_dev, 0);
 267        iio_device_unregister(indio_dev);
 268        iio_free_device(chip->indio_dev);
 269        kfree(chip);
 270
 271        return 0;
 272}
 273
 274static const struct spi_device_id ad7314_id[] = {
 275        { "adt7301", 0 },
 276        { "adt7302", 0 },
 277        { "ad7314", 0 },
 278        {}
 279};
 280
 281static struct spi_driver ad7314_driver = {
 282        .driver = {
 283                .name = "ad7314",
 284                .bus = &spi_bus_type,
 285                .owner = THIS_MODULE,
 286        },
 287        .probe = ad7314_probe,
 288        .remove = __devexit_p(ad7314_remove),
 289        .id_table = ad7314_id,
 290};
 291
 292static __init int ad7314_init(void)
 293{
 294        return spi_register_driver(&ad7314_driver);
 295}
 296
 297static __exit void ad7314_exit(void)
 298{
 299        spi_unregister_driver(&ad7314_driver);
 300}
 301
 302MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
 303MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
 304                        " temperature sensor driver");
 305MODULE_LICENSE("GPL v2");
 306
 307module_init(ad7314_init);
 308module_exit(ad7314_exit);
 309