root/drivers/hwmon/ad7418.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ad7418_update_device
  2. temp_show
  3. adc_show
  4. temp_store
  5. ad7418_init_client
  6. ad7418_probe

   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 
  27 enum 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 
  40 static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN,
  41                                         AD7418_REG_TEMP_HYST,
  42                                         AD7418_REG_TEMP_OS };
  43 
  44 struct 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 
  55 static 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 
 120 abort:
 121         data->valid = 0;
 122         mutex_unlock(&data->lock);
 123         return val;
 124 }
 125 
 126 static 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 
 141 static 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 
 156 static 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 
 178 static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
 179 static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp, 1);
 180 static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 2);
 181 
 182 static SENSOR_DEVICE_ATTR_RO(in1_input, adc, 0);
 183 static SENSOR_DEVICE_ATTR_RO(in2_input, adc, 1);
 184 static SENSOR_DEVICE_ATTR_RO(in3_input, adc, 2);
 185 static SENSOR_DEVICE_ATTR_RO(in4_input, adc, 3);
 186 
 187 static 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 };
 193 ATTRIBUTE_GROUPS(ad7416);
 194 
 195 static 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 };
 205 ATTRIBUTE_GROUPS(ad7417);
 206 
 207 static 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 };
 214 ATTRIBUTE_GROUPS(ad7418);
 215 
 216 static 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 
 233 static int ad7418_probe(struct i2c_client *client,
 234                          const struct i2c_device_id *id)
 235 {
 236         struct device *dev = &client->dev;
 237         struct i2c_adapter *adapter = client->adapter;
 238         struct ad7418_data *data;
 239         struct device *hwmon_dev;
 240         const struct attribute_group **attr_groups = NULL;
 241 
 242         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 243                                         I2C_FUNC_SMBUS_WORD_DATA))
 244                 return -EOPNOTSUPP;
 245 
 246         data = devm_kzalloc(dev, sizeof(struct ad7418_data), GFP_KERNEL);
 247         if (!data)
 248                 return -ENOMEM;
 249 
 250         i2c_set_clientdata(client, data);
 251 
 252         mutex_init(&data->lock);
 253         data->client = client;
 254         if (dev->of_node)
 255                 data->type = (enum chips)of_device_get_match_data(dev);
 256         else
 257                 data->type = id->driver_data;
 258 
 259         switch (data->type) {
 260         case ad7416:
 261                 data->adc_max = 0;
 262                 attr_groups = ad7416_groups;
 263                 break;
 264 
 265         case ad7417:
 266                 data->adc_max = 4;
 267                 attr_groups = ad7417_groups;
 268                 break;
 269 
 270         case ad7418:
 271                 data->adc_max = 1;
 272                 attr_groups = ad7418_groups;
 273                 break;
 274         }
 275 
 276         dev_info(dev, "%s chip found\n", client->name);
 277 
 278         /* Initialize the AD7418 chip */
 279         ad7418_init_client(client);
 280 
 281         hwmon_dev = devm_hwmon_device_register_with_groups(dev,
 282                                                            client->name,
 283                                                            data, attr_groups);
 284         return PTR_ERR_OR_ZERO(hwmon_dev);
 285 }
 286 
 287 static const struct i2c_device_id ad7418_id[] = {
 288         { "ad7416", ad7416 },
 289         { "ad7417", ad7417 },
 290         { "ad7418", ad7418 },
 291         { }
 292 };
 293 MODULE_DEVICE_TABLE(i2c, ad7418_id);
 294 
 295 static const struct of_device_id ad7418_dt_ids[] = {
 296         { .compatible = "adi,ad7416", .data = (void *)ad7416, },
 297         { .compatible = "adi,ad7417", .data = (void *)ad7417, },
 298         { .compatible = "adi,ad7418", .data = (void *)ad7418, },
 299         { }
 300 };
 301 MODULE_DEVICE_TABLE(of, ad7418_dt_ids);
 302 
 303 static struct i2c_driver ad7418_driver = {
 304         .driver = {
 305                 .name   = "ad7418",
 306                 .of_match_table = ad7418_dt_ids,
 307         },
 308         .probe          = ad7418_probe,
 309         .id_table       = ad7418_id,
 310 };
 311 
 312 module_i2c_driver(ad7418_driver);
 313 
 314 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
 315 MODULE_DESCRIPTION("AD7416/17/18 driver");
 316 MODULE_LICENSE("GPL");
 317 MODULE_VERSION(DRV_VERSION);

/* [<][>][^][v][top][bottom][index][help] */