Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * An hwmon driver for the Analog Devices AD7416/17/18
0004  * Copyright (C) 2006-07 Tower Technologies
0005  *
0006  * Author: Alessandro Zummo <a.zummo@towertech.it>
0007  *
0008  * Based on lm75.c
0009  * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/jiffies.h>
0014 #include <linux/i2c.h>
0015 #include <linux/hwmon.h>
0016 #include <linux/hwmon-sysfs.h>
0017 #include <linux/err.h>
0018 #include <linux/mutex.h>
0019 #include <linux/of_device.h>
0020 #include <linux/delay.h>
0021 #include <linux/slab.h>
0022 
0023 #include "lm75.h"
0024 
0025 #define DRV_VERSION "0.4"
0026 
0027 enum chips { ad7416, ad7417, ad7418 };
0028 
0029 /* AD7418 registers */
0030 #define AD7418_REG_TEMP_IN  0x00
0031 #define AD7418_REG_CONF     0x01
0032 #define AD7418_REG_TEMP_HYST    0x02
0033 #define AD7418_REG_TEMP_OS  0x03
0034 #define AD7418_REG_ADC      0x04
0035 #define AD7418_REG_CONF2    0x05
0036 
0037 #define AD7418_REG_ADC_CH(x)    ((x) << 5)
0038 #define AD7418_CH_TEMP      AD7418_REG_ADC_CH(0)
0039 
0040 static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN,
0041                     AD7418_REG_TEMP_HYST,
0042                     AD7418_REG_TEMP_OS };
0043 
0044 struct ad7418_data {
0045     struct i2c_client   *client;
0046     enum chips      type;
0047     struct mutex        lock;
0048     int         adc_max;    /* number of ADC channels */
0049     bool            valid;
0050     unsigned long       last_updated;   /* In jiffies */
0051     s16         temp[3];    /* Register values */
0052     u16         in[4];
0053 };
0054 
0055 static int ad7418_update_device(struct device *dev)
0056 {
0057     struct ad7418_data *data = dev_get_drvdata(dev);
0058     struct i2c_client *client = data->client;
0059     s32 val;
0060 
0061     mutex_lock(&data->lock);
0062 
0063     if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
0064         || !data->valid) {
0065         u8 cfg;
0066         int i, ch;
0067 
0068         /* read config register and clear channel bits */
0069         val = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
0070         if (val < 0)
0071             goto abort;
0072 
0073         cfg = val;
0074         cfg &= 0x1F;
0075 
0076         val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
0077                         cfg | AD7418_CH_TEMP);
0078         if (val < 0)
0079             goto abort;
0080 
0081         udelay(30);
0082 
0083         for (i = 0; i < 3; i++) {
0084             val = i2c_smbus_read_word_swapped(client,
0085                               AD7418_REG_TEMP[i]);
0086             if (val < 0)
0087                 goto abort;
0088 
0089             data->temp[i] = val;
0090         }
0091 
0092         for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
0093             val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
0094                     cfg | AD7418_REG_ADC_CH(ch));
0095             if (val < 0)
0096                 goto abort;
0097 
0098             udelay(15);
0099             val = i2c_smbus_read_word_swapped(client,
0100                               AD7418_REG_ADC);
0101             if (val < 0)
0102                 goto abort;
0103 
0104             data->in[data->adc_max - 1 - i] = val;
0105         }
0106 
0107         /* restore old configuration value */
0108         val = i2c_smbus_write_word_swapped(client, AD7418_REG_CONF,
0109                            cfg);
0110         if (val < 0)
0111             goto abort;
0112 
0113         data->last_updated = jiffies;
0114         data->valid = true;
0115     }
0116 
0117     mutex_unlock(&data->lock);
0118     return 0;
0119 
0120 abort:
0121     data->valid = false;
0122     mutex_unlock(&data->lock);
0123     return val;
0124 }
0125 
0126 static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
0127              char *buf)
0128 {
0129     struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
0130     struct ad7418_data *data = dev_get_drvdata(dev);
0131     int ret;
0132 
0133     ret = ad7418_update_device(dev);
0134     if (ret < 0)
0135         return ret;
0136 
0137     return sprintf(buf, "%d\n",
0138         LM75_TEMP_FROM_REG(data->temp[attr->index]));
0139 }
0140 
0141 static ssize_t adc_show(struct device *dev, struct device_attribute *devattr,
0142             char *buf)
0143 {
0144     struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
0145     struct ad7418_data *data = dev_get_drvdata(dev);
0146     int ret;
0147 
0148     ret = ad7418_update_device(dev);
0149     if (ret < 0)
0150         return ret;
0151 
0152     return sprintf(buf, "%d\n",
0153         ((data->in[attr->index] >> 6) * 2500 + 512) / 1024);
0154 }
0155 
0156 static ssize_t temp_store(struct device *dev,
0157               struct device_attribute *devattr, const char *buf,
0158               size_t count)
0159 {
0160     struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
0161     struct ad7418_data *data = dev_get_drvdata(dev);
0162     struct i2c_client *client = data->client;
0163     long temp;
0164     int ret = kstrtol(buf, 10, &temp);
0165 
0166     if (ret < 0)
0167         return ret;
0168 
0169     mutex_lock(&data->lock);
0170     data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
0171     i2c_smbus_write_word_swapped(client,
0172                      AD7418_REG_TEMP[attr->index],
0173                      data->temp[attr->index]);
0174     mutex_unlock(&data->lock);
0175     return count;
0176 }
0177 
0178 static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
0179 static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp, 1);
0180 static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 2);
0181 
0182 static SENSOR_DEVICE_ATTR_RO(in1_input, adc, 0);
0183 static SENSOR_DEVICE_ATTR_RO(in2_input, adc, 1);
0184 static SENSOR_DEVICE_ATTR_RO(in3_input, adc, 2);
0185 static SENSOR_DEVICE_ATTR_RO(in4_input, adc, 3);
0186 
0187 static struct attribute *ad7416_attrs[] = {
0188     &sensor_dev_attr_temp1_max.dev_attr.attr,
0189     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
0190     &sensor_dev_attr_temp1_input.dev_attr.attr,
0191     NULL
0192 };
0193 ATTRIBUTE_GROUPS(ad7416);
0194 
0195 static struct attribute *ad7417_attrs[] = {
0196     &sensor_dev_attr_temp1_max.dev_attr.attr,
0197     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
0198     &sensor_dev_attr_temp1_input.dev_attr.attr,
0199     &sensor_dev_attr_in1_input.dev_attr.attr,
0200     &sensor_dev_attr_in2_input.dev_attr.attr,
0201     &sensor_dev_attr_in3_input.dev_attr.attr,
0202     &sensor_dev_attr_in4_input.dev_attr.attr,
0203     NULL
0204 };
0205 ATTRIBUTE_GROUPS(ad7417);
0206 
0207 static struct attribute *ad7418_attrs[] = {
0208     &sensor_dev_attr_temp1_max.dev_attr.attr,
0209     &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
0210     &sensor_dev_attr_temp1_input.dev_attr.attr,
0211     &sensor_dev_attr_in1_input.dev_attr.attr,
0212     NULL
0213 };
0214 ATTRIBUTE_GROUPS(ad7418);
0215 
0216 static void ad7418_init_client(struct i2c_client *client)
0217 {
0218     struct ad7418_data *data = i2c_get_clientdata(client);
0219 
0220     int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
0221     if (reg < 0) {
0222         dev_err(&client->dev, "cannot read configuration register\n");
0223     } else {
0224         dev_info(&client->dev, "configuring for mode 1\n");
0225         i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
0226 
0227         if (data->type == ad7417 || data->type == ad7418)
0228             i2c_smbus_write_byte_data(client,
0229                         AD7418_REG_CONF2, 0x00);
0230     }
0231 }
0232 
0233 static const struct i2c_device_id ad7418_id[];
0234 
0235 static int ad7418_probe(struct i2c_client *client)
0236 {
0237     struct device *dev = &client->dev;
0238     struct i2c_adapter *adapter = client->adapter;
0239     struct ad7418_data *data;
0240     struct device *hwmon_dev;
0241     const struct attribute_group **attr_groups = NULL;
0242 
0243     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
0244                     I2C_FUNC_SMBUS_WORD_DATA))
0245         return -EOPNOTSUPP;
0246 
0247     data = devm_kzalloc(dev, sizeof(struct ad7418_data), GFP_KERNEL);
0248     if (!data)
0249         return -ENOMEM;
0250 
0251     i2c_set_clientdata(client, data);
0252 
0253     mutex_init(&data->lock);
0254     data->client = client;
0255     if (dev->of_node)
0256         data->type = (enum chips)of_device_get_match_data(dev);
0257     else
0258         data->type = i2c_match_id(ad7418_id, client)->driver_data;
0259 
0260     switch (data->type) {
0261     case ad7416:
0262         data->adc_max = 0;
0263         attr_groups = ad7416_groups;
0264         break;
0265 
0266     case ad7417:
0267         data->adc_max = 4;
0268         attr_groups = ad7417_groups;
0269         break;
0270 
0271     case ad7418:
0272         data->adc_max = 1;
0273         attr_groups = ad7418_groups;
0274         break;
0275     }
0276 
0277     dev_info(dev, "%s chip found\n", client->name);
0278 
0279     /* Initialize the AD7418 chip */
0280     ad7418_init_client(client);
0281 
0282     hwmon_dev = devm_hwmon_device_register_with_groups(dev,
0283                                client->name,
0284                                data, attr_groups);
0285     return PTR_ERR_OR_ZERO(hwmon_dev);
0286 }
0287 
0288 static const struct i2c_device_id ad7418_id[] = {
0289     { "ad7416", ad7416 },
0290     { "ad7417", ad7417 },
0291     { "ad7418", ad7418 },
0292     { }
0293 };
0294 MODULE_DEVICE_TABLE(i2c, ad7418_id);
0295 
0296 static const struct of_device_id ad7418_dt_ids[] = {
0297     { .compatible = "adi,ad7416", .data = (void *)ad7416, },
0298     { .compatible = "adi,ad7417", .data = (void *)ad7417, },
0299     { .compatible = "adi,ad7418", .data = (void *)ad7418, },
0300     { }
0301 };
0302 MODULE_DEVICE_TABLE(of, ad7418_dt_ids);
0303 
0304 static struct i2c_driver ad7418_driver = {
0305     .driver = {
0306         .name   = "ad7418",
0307         .of_match_table = ad7418_dt_ids,
0308     },
0309     .probe_new  = ad7418_probe,
0310     .id_table   = ad7418_id,
0311 };
0312 
0313 module_i2c_driver(ad7418_driver);
0314 
0315 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
0316 MODULE_DESCRIPTION("AD7416/17/18 driver");
0317 MODULE_LICENSE("GPL");
0318 MODULE_VERSION(DRV_VERSION);