linux/drivers/hwmon/ad7418.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * An hwmon driver for the Analog Devices AD7416/17/18
   4 * Copyright (C) 2006-07 Tower Technologies
   5 *
   6 * Author: Alessandro Zummo <a.zummo@towertech.it>
   7 *
   8 * Based on lm75.c
   9 * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/jiffies.h>
  14#include <linux/i2c.h>
  15#include <linux/hwmon.h>
  16#include <linux/hwmon-sysfs.h>
  17#include <linux/err.h>
  18#include <linux/mutex.h>
  19#include <linux/of_device.h>
  20#include <linux/delay.h>
  21#include <linux/slab.h>
  22
  23#include "lm75.h"
  24
  25#define DRV_VERSION "0.4"
  26
  27enum chips { ad7416, ad7417, ad7418 };
  28
  29/* AD7418 registers */
  30#define AD7418_REG_TEMP_IN      0x00
  31#define AD7418_REG_CONF         0x01
  32#define AD7418_REG_TEMP_HYST    0x02
  33#define AD7418_REG_TEMP_OS      0x03
  34#define AD7418_REG_ADC          0x04
  35#define AD7418_REG_CONF2        0x05
  36
  37#define AD7418_REG_ADC_CH(x)    ((x) << 5)
  38#define AD7418_CH_TEMP          AD7418_REG_ADC_CH(0)
  39
  40static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN,
  41                                        AD7418_REG_TEMP_HYST,
  42                                        AD7418_REG_TEMP_OS };
  43
  44struct ad7418_data {
  45        struct i2c_client       *client;
  46        enum chips              type;
  47        struct mutex            lock;
  48        int                     adc_max;        /* number of ADC channels */
  49        char                    valid;
  50        unsigned long           last_updated;   /* In jiffies */
  51        s16                     temp[3];        /* Register values */
  52        u16                     in[4];
  53};
  54
  55static int ad7418_update_device(struct device *dev)
  56{
  57        struct ad7418_data *data = dev_get_drvdata(dev);
  58        struct i2c_client *client = data->client;
  59        s32 val;
  60
  61        mutex_lock(&data->lock);
  62
  63        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
  64                || !data->valid) {
  65                u8 cfg;
  66                int i, ch;
  67
  68                /* read config register and clear channel bits */
  69                val = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
  70                if (val < 0)
  71                        goto abort;
  72
  73                cfg = val;
  74                cfg &= 0x1F;
  75
  76                val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
  77                                                cfg | AD7418_CH_TEMP);
  78                if (val < 0)
  79                        goto abort;
  80
  81                udelay(30);
  82
  83                for (i = 0; i < 3; i++) {
  84                        val = i2c_smbus_read_word_swapped(client,
  85                                                          AD7418_REG_TEMP[i]);
  86                        if (val < 0)
  87                                goto abort;
  88
  89                        data->temp[i] = val;
  90                }
  91
  92                for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
  93                        val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
  94                                        cfg | AD7418_REG_ADC_CH(ch));
  95                        if (val < 0)
  96                                goto abort;
  97
  98                        udelay(15);
  99                        val = i2c_smbus_read_word_swapped(client,
 100                                                          AD7418_REG_ADC);
 101                        if (val < 0)
 102                                goto abort;
 103
 104                        data->in[data->adc_max - 1 - i] = val;
 105                }
 106
 107                /* restore old configuration value */
 108                val = i2c_smbus_write_word_swapped(client, AD7418_REG_CONF,
 109                                                   cfg);
 110                if (val < 0)
 111                        goto abort;
 112
 113                data->last_updated = jiffies;
 114                data->valid = 1;
 115        }
 116
 117        mutex_unlock(&data->lock);
 118        return 0;
 119
 120abort:
 121        data->valid = 0;
 122        mutex_unlock(&data->lock);
 123        return val;
 124}
 125
 126static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
 127                         char *buf)
 128{
 129        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 130        struct ad7418_data *data = dev_get_drvdata(dev);
 131        int ret;
 132
 133        ret = ad7418_update_device(dev);
 134        if (ret < 0)
 135                return ret;
 136
 137        return sprintf(buf, "%d\n",
 138                LM75_TEMP_FROM_REG(data->temp[attr->index]));
 139}
 140
 141static ssize_t adc_show(struct device *dev, struct device_attribute *devattr,
 142                        char *buf)
 143{
 144        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 145        struct ad7418_data *data = dev_get_drvdata(dev);
 146        int ret;
 147
 148        ret = ad7418_update_device(dev);
 149        if (ret < 0)
 150                return ret;
 151
 152        return sprintf(buf, "%d\n",
 153                ((data->in[attr->index] >> 6) * 2500 + 512) / 1024);
 154}
 155
 156static ssize_t temp_store(struct device *dev,
 157                          struct device_attribute *devattr, const char *buf,
 158                          size_t count)
 159{
 160        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 161        struct ad7418_data *data = dev_get_drvdata(dev);
 162        struct i2c_client *client = data->client;
 163        long temp;
 164        int ret = kstrtol(buf, 10, &temp);
 165
 166        if (ret < 0)
 167                return ret;
 168
 169        mutex_lock(&data->lock);
 170        data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
 171        i2c_smbus_write_word_swapped(client,
 172                                     AD7418_REG_TEMP[attr->index],
 173                                     data->temp[attr->index]);
 174        mutex_unlock(&data->lock);
 175        return count;
 176}
 177
 178static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
 179static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp, 1);
 180static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 2);
 181
 182static SENSOR_DEVICE_ATTR_RO(in1_input, adc, 0);
 183static SENSOR_DEVICE_ATTR_RO(in2_input, adc, 1);
 184static SENSOR_DEVICE_ATTR_RO(in3_input, adc, 2);
 185static SENSOR_DEVICE_ATTR_RO(in4_input, adc, 3);
 186
 187static struct attribute *ad7416_attrs[] = {
 188        &sensor_dev_attr_temp1_max.dev_attr.attr,
 189        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 190        &sensor_dev_attr_temp1_input.dev_attr.attr,
 191        NULL
 192};
 193ATTRIBUTE_GROUPS(ad7416);
 194
 195static struct attribute *ad7417_attrs[] = {
 196        &sensor_dev_attr_temp1_max.dev_attr.attr,
 197        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 198        &sensor_dev_attr_temp1_input.dev_attr.attr,
 199        &sensor_dev_attr_in1_input.dev_attr.attr,
 200        &sensor_dev_attr_in2_input.dev_attr.attr,
 201        &sensor_dev_attr_in3_input.dev_attr.attr,
 202        &sensor_dev_attr_in4_input.dev_attr.attr,
 203        NULL
 204};
 205ATTRIBUTE_GROUPS(ad7417);
 206
 207static struct attribute *ad7418_attrs[] = {
 208        &sensor_dev_attr_temp1_max.dev_attr.attr,
 209        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 210        &sensor_dev_attr_temp1_input.dev_attr.attr,
 211        &sensor_dev_attr_in1_input.dev_attr.attr,
 212        NULL
 213};
 214ATTRIBUTE_GROUPS(ad7418);
 215
 216static void ad7418_init_client(struct i2c_client *client)
 217{
 218        struct ad7418_data *data = i2c_get_clientdata(client);
 219
 220        int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
 221        if (reg < 0) {
 222                dev_err(&client->dev, "cannot read configuration register\n");
 223        } else {
 224                dev_info(&client->dev, "configuring for mode 1\n");
 225                i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
 226
 227                if (data->type == ad7417 || data->type == ad7418)
 228                        i2c_smbus_write_byte_data(client,
 229                                                AD7418_REG_CONF2, 0x00);
 230        }
 231}
 232
 233static const struct i2c_device_id ad7418_id[];
 234
 235static int ad7418_probe(struct i2c_client *client)
 236{
 237        struct device *dev = &client->dev;
 238        struct i2c_adapter *adapter = client->adapter;
 239        struct ad7418_data *data;
 240        struct device *hwmon_dev;
 241        const struct attribute_group **attr_groups = NULL;
 242
 243        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 244                                        I2C_FUNC_SMBUS_WORD_DATA))
 245                return -EOPNOTSUPP;
 246
 247        data = devm_kzalloc(dev, sizeof(struct ad7418_data), GFP_KERNEL);
 248        if (!data)
 249                return -ENOMEM;
 250
 251        i2c_set_clientdata(client, data);
 252
 253        mutex_init(&data->lock);
 254        data->client = client;
 255        if (dev->of_node)
 256                data->type = (enum chips)of_device_get_match_data(dev);
 257        else
 258                data->type = i2c_match_id(ad7418_id, client)->driver_data;
 259
 260        switch (data->type) {
 261        case ad7416:
 262                data->adc_max = 0;
 263                attr_groups = ad7416_groups;
 264                break;
 265
 266        case ad7417:
 267                data->adc_max = 4;
 268                attr_groups = ad7417_groups;
 269                break;
 270
 271        case ad7418:
 272                data->adc_max = 1;
 273                attr_groups = ad7418_groups;
 274                break;
 275        }
 276
 277        dev_info(dev, "%s chip found\n", client->name);
 278
 279        /* Initialize the AD7418 chip */
 280        ad7418_init_client(client);
 281
 282        hwmon_dev = devm_hwmon_device_register_with_groups(dev,
 283                                                           client->name,
 284                                                           data, attr_groups);
 285        return PTR_ERR_OR_ZERO(hwmon_dev);
 286}
 287
 288static const struct i2c_device_id ad7418_id[] = {
 289        { "ad7416", ad7416 },
 290        { "ad7417", ad7417 },
 291        { "ad7418", ad7418 },
 292        { }
 293};
 294MODULE_DEVICE_TABLE(i2c, ad7418_id);
 295
 296static const struct of_device_id ad7418_dt_ids[] = {
 297        { .compatible = "adi,ad7416", .data = (void *)ad7416, },
 298        { .compatible = "adi,ad7417", .data = (void *)ad7417, },
 299        { .compatible = "adi,ad7418", .data = (void *)ad7418, },
 300        { }
 301};
 302MODULE_DEVICE_TABLE(of, ad7418_dt_ids);
 303
 304static struct i2c_driver ad7418_driver = {
 305        .driver = {
 306                .name   = "ad7418",
 307                .of_match_table = ad7418_dt_ids,
 308        },
 309        .probe_new      = ad7418_probe,
 310        .id_table       = ad7418_id,
 311};
 312
 313module_i2c_driver(ad7418_driver);
 314
 315MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
 316MODULE_DESCRIPTION("AD7416/17/18 driver");
 317MODULE_LICENSE("GPL");
 318MODULE_VERSION(DRV_VERSION);
 319