Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * An hwmon driver for the Analog Devices AD7414
0004  *
0005  * Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
0006  *
0007  * Copyright (c) 2008 PIKA Technologies
0008  *   Sean MacLennan <smaclennan@pikatech.com>
0009  *
0010  * Copyright (c) 2008 Spansion Inc.
0011  *   Frank Edelhaeuser <frank.edelhaeuser at spansion.com>
0012  *   (converted to "new style" I2C driver model, removed checkpatch.pl warnings)
0013  *
0014  * Based on ad7418.c
0015  * Copyright 2006 Tower Technologies, Alessandro Zummo <a.zummo at towertech.it>
0016  */
0017 
0018 #include <linux/module.h>
0019 #include <linux/jiffies.h>
0020 #include <linux/i2c.h>
0021 #include <linux/hwmon.h>
0022 #include <linux/hwmon-sysfs.h>
0023 #include <linux/err.h>
0024 #include <linux/mutex.h>
0025 #include <linux/sysfs.h>
0026 #include <linux/slab.h>
0027 
0028 
0029 /* AD7414 registers */
0030 #define AD7414_REG_TEMP     0x00
0031 #define AD7414_REG_CONF     0x01
0032 #define AD7414_REG_T_HIGH   0x02
0033 #define AD7414_REG_T_LOW    0x03
0034 
0035 static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW };
0036 
0037 struct ad7414_data {
0038     struct i2c_client   *client;
0039     struct mutex        lock;   /* atomic read data updates */
0040     bool            valid;  /* true if following fields are valid */
0041     unsigned long       next_update;    /* In jiffies */
0042     s16         temp_input; /* Register values */
0043     s8          temps[ARRAY_SIZE(AD7414_REG_LIMIT)];
0044 };
0045 
0046 /* REG: (0.25C/bit, two's complement) << 6 */
0047 static inline int ad7414_temp_from_reg(s16 reg)
0048 {
0049     /*
0050      * use integer division instead of equivalent right shift to
0051      * guarantee arithmetic shift and preserve the sign
0052      */
0053     return ((int)reg / 64) * 250;
0054 }
0055 
0056 static inline int ad7414_read(struct i2c_client *client, u8 reg)
0057 {
0058     if (reg == AD7414_REG_TEMP)
0059         return i2c_smbus_read_word_swapped(client, reg);
0060     else
0061         return i2c_smbus_read_byte_data(client, reg);
0062 }
0063 
0064 static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value)
0065 {
0066     return i2c_smbus_write_byte_data(client, reg, value);
0067 }
0068 
0069 static struct ad7414_data *ad7414_update_device(struct device *dev)
0070 {
0071     struct ad7414_data *data = dev_get_drvdata(dev);
0072     struct i2c_client *client = data->client;
0073 
0074     mutex_lock(&data->lock);
0075 
0076     if (time_after(jiffies, data->next_update) || !data->valid) {
0077         int value, i;
0078 
0079         dev_dbg(&client->dev, "starting ad7414 update\n");
0080 
0081         value = ad7414_read(client, AD7414_REG_TEMP);
0082         if (value < 0)
0083             dev_dbg(&client->dev, "AD7414_REG_TEMP err %d\n",
0084                 value);
0085         else
0086             data->temp_input = value;
0087 
0088         for (i = 0; i < ARRAY_SIZE(AD7414_REG_LIMIT); ++i) {
0089             value = ad7414_read(client, AD7414_REG_LIMIT[i]);
0090             if (value < 0)
0091                 dev_dbg(&client->dev, "AD7414 reg %d err %d\n",
0092                     AD7414_REG_LIMIT[i], value);
0093             else
0094                 data->temps[i] = value;
0095         }
0096 
0097         data->next_update = jiffies + HZ + HZ / 2;
0098         data->valid = true;
0099     }
0100 
0101     mutex_unlock(&data->lock);
0102 
0103     return data;
0104 }
0105 
0106 static ssize_t temp_input_show(struct device *dev,
0107                    struct device_attribute *attr, char *buf)
0108 {
0109     struct ad7414_data *data = ad7414_update_device(dev);
0110     return sprintf(buf, "%d\n", ad7414_temp_from_reg(data->temp_input));
0111 }
0112 static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
0113 
0114 static ssize_t max_min_show(struct device *dev, struct device_attribute *attr,
0115                 char *buf)
0116 {
0117     int index = to_sensor_dev_attr(attr)->index;
0118     struct ad7414_data *data = ad7414_update_device(dev);
0119     return sprintf(buf, "%d\n", data->temps[index] * 1000);
0120 }
0121 
0122 static ssize_t max_min_store(struct device *dev,
0123                  struct device_attribute *attr, const char *buf,
0124                  size_t count)
0125 {
0126     struct ad7414_data *data = dev_get_drvdata(dev);
0127     struct i2c_client *client = data->client;
0128     int index = to_sensor_dev_attr(attr)->index;
0129     u8 reg = AD7414_REG_LIMIT[index];
0130     long temp;
0131     int ret = kstrtol(buf, 10, &temp);
0132 
0133     if (ret < 0)
0134         return ret;
0135 
0136     temp = clamp_val(temp, -40000, 85000);
0137     temp = (temp + (temp < 0 ? -500 : 500)) / 1000;
0138 
0139     mutex_lock(&data->lock);
0140     data->temps[index] = temp;
0141     ad7414_write(client, reg, temp);
0142     mutex_unlock(&data->lock);
0143     return count;
0144 }
0145 
0146 static SENSOR_DEVICE_ATTR_RW(temp1_max, max_min, 0);
0147 static SENSOR_DEVICE_ATTR_RW(temp1_min, max_min, 1);
0148 
0149 static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
0150               char *buf)
0151 {
0152     int bitnr = to_sensor_dev_attr(attr)->index;
0153     struct ad7414_data *data = ad7414_update_device(dev);
0154     int value = (data->temp_input >> bitnr) & 1;
0155     return sprintf(buf, "%d\n", value);
0156 }
0157 
0158 static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 3);
0159 static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 4);
0160 
0161 static struct attribute *ad7414_attrs[] = {
0162     &sensor_dev_attr_temp1_input.dev_attr.attr,
0163     &sensor_dev_attr_temp1_max.dev_attr.attr,
0164     &sensor_dev_attr_temp1_min.dev_attr.attr,
0165     &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
0166     &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
0167     NULL
0168 };
0169 
0170 ATTRIBUTE_GROUPS(ad7414);
0171 
0172 static int ad7414_probe(struct i2c_client *client)
0173 {
0174     struct device *dev = &client->dev;
0175     struct ad7414_data *data;
0176     struct device *hwmon_dev;
0177     int conf;
0178 
0179     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
0180                      I2C_FUNC_SMBUS_READ_WORD_DATA))
0181         return -EOPNOTSUPP;
0182 
0183     data = devm_kzalloc(dev, sizeof(struct ad7414_data), GFP_KERNEL);
0184     if (!data)
0185         return -ENOMEM;
0186 
0187     data->client = client;
0188     mutex_init(&data->lock);
0189 
0190     dev_info(&client->dev, "chip found\n");
0191 
0192     /* Make sure the chip is powered up. */
0193     conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF);
0194     if (conf < 0)
0195         dev_warn(dev, "ad7414_probe unable to read config register.\n");
0196     else {
0197         conf &= ~(1 << 7);
0198         i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf);
0199     }
0200 
0201     hwmon_dev = devm_hwmon_device_register_with_groups(dev,
0202                                client->name,
0203                                data, ad7414_groups);
0204     return PTR_ERR_OR_ZERO(hwmon_dev);
0205 }
0206 
0207 static const struct i2c_device_id ad7414_id[] = {
0208     { "ad7414", 0 },
0209     {}
0210 };
0211 MODULE_DEVICE_TABLE(i2c, ad7414_id);
0212 
0213 static const struct of_device_id __maybe_unused ad7414_of_match[] = {
0214     { .compatible = "ad,ad7414" },
0215     { },
0216 };
0217 MODULE_DEVICE_TABLE(of, ad7414_of_match);
0218 
0219 static struct i2c_driver ad7414_driver = {
0220     .driver = {
0221         .name   = "ad7414",
0222         .of_match_table = of_match_ptr(ad7414_of_match),
0223     },
0224     .probe_new = ad7414_probe,
0225     .id_table = ad7414_id,
0226 };
0227 
0228 module_i2c_driver(ad7414_driver);
0229 
0230 MODULE_AUTHOR("Stefan Roese <sr at denx.de>, "
0231           "Frank Edelhaeuser <frank.edelhaeuser at spansion.com>");
0232 
0233 MODULE_DESCRIPTION("AD7414 driver");
0234 MODULE_LICENSE("GPL");