0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/slab.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/sysfs.h>
0020 #include <linux/platform_data/ds620.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #define DS620_REG_CONFIG_DONE 0x8000
0031 #define DS620_REG_CONFIG_NVB 0x4000
0032 #define DS620_REG_CONFIG_THF 0x2000
0033 #define DS620_REG_CONFIG_TLF 0x1000
0034 #define DS620_REG_CONFIG_R1 0x0800
0035 #define DS620_REG_CONFIG_R0 0x0400
0036 #define DS620_REG_CONFIG_AUTOC 0x0200
0037 #define DS620_REG_CONFIG_1SHOT 0x0100
0038 #define DS620_REG_CONFIG_PO2 0x0080
0039 #define DS620_REG_CONFIG_PO1 0x0040
0040 #define DS620_REG_CONFIG_A2 0x0020
0041 #define DS620_REG_CONFIG_A1 0x0010
0042 #define DS620_REG_CONFIG_A0 0x0008
0043
0044
0045 static const u8 DS620_REG_TEMP[3] = {
0046 0xAA,
0047 0xA2,
0048 0xA0,
0049 };
0050
0051 #define DS620_REG_CONF 0xAC
0052 #define DS620_COM_START 0x51
0053 #define DS620_COM_STOP 0x22
0054
0055
0056 struct ds620_data {
0057 struct i2c_client *client;
0058 struct mutex update_lock;
0059 bool valid;
0060 unsigned long last_updated;
0061
0062 s16 temp[3];
0063 };
0064
0065 static void ds620_init_client(struct i2c_client *client)
0066 {
0067 struct ds620_platform_data *ds620_info = dev_get_platdata(&client->dev);
0068 u16 conf, new_conf;
0069
0070 new_conf = conf =
0071 i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
0072
0073
0074 new_conf &= ~DS620_REG_CONFIG_1SHOT;
0075
0076 new_conf |= DS620_REG_CONFIG_PO2;
0077
0078 if (ds620_info && ds620_info->pomode == 1)
0079 new_conf &= ~DS620_REG_CONFIG_PO1;
0080 else if (ds620_info && ds620_info->pomode == 2)
0081 new_conf |= DS620_REG_CONFIG_PO1;
0082 else
0083 new_conf &= ~DS620_REG_CONFIG_PO2;
0084
0085 new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0;
0086
0087 if (conf != new_conf)
0088 i2c_smbus_write_word_swapped(client, DS620_REG_CONF, new_conf);
0089
0090
0091 i2c_smbus_write_byte(client, DS620_COM_START);
0092 }
0093
0094 static struct ds620_data *ds620_update_client(struct device *dev)
0095 {
0096 struct ds620_data *data = dev_get_drvdata(dev);
0097 struct i2c_client *client = data->client;
0098 struct ds620_data *ret = data;
0099
0100 mutex_lock(&data->update_lock);
0101
0102 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
0103 || !data->valid) {
0104 int i;
0105 int res;
0106
0107 dev_dbg(&client->dev, "Starting ds620 update\n");
0108
0109 for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
0110 res = i2c_smbus_read_word_swapped(client,
0111 DS620_REG_TEMP[i]);
0112 if (res < 0) {
0113 ret = ERR_PTR(res);
0114 goto abort;
0115 }
0116
0117 data->temp[i] = res;
0118 }
0119
0120 data->last_updated = jiffies;
0121 data->valid = true;
0122 }
0123 abort:
0124 mutex_unlock(&data->update_lock);
0125
0126 return ret;
0127 }
0128
0129 static ssize_t temp_show(struct device *dev, struct device_attribute *da,
0130 char *buf)
0131 {
0132 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
0133 struct ds620_data *data = ds620_update_client(dev);
0134
0135 if (IS_ERR(data))
0136 return PTR_ERR(data);
0137
0138 return sprintf(buf, "%d\n", ((data->temp[attr->index] / 8) * 625) / 10);
0139 }
0140
0141 static ssize_t temp_store(struct device *dev, struct device_attribute *da,
0142 const char *buf, size_t count)
0143 {
0144 int res;
0145 long val;
0146
0147 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
0148 struct ds620_data *data = dev_get_drvdata(dev);
0149 struct i2c_client *client = data->client;
0150
0151 res = kstrtol(buf, 10, &val);
0152
0153 if (res)
0154 return res;
0155
0156 val = (clamp_val(val, -128000, 128000) * 10 / 625) * 8;
0157
0158 mutex_lock(&data->update_lock);
0159 data->temp[attr->index] = val;
0160 i2c_smbus_write_word_swapped(client, DS620_REG_TEMP[attr->index],
0161 data->temp[attr->index]);
0162 mutex_unlock(&data->update_lock);
0163 return count;
0164 }
0165
0166 static ssize_t alarm_show(struct device *dev, struct device_attribute *da,
0167 char *buf)
0168 {
0169 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
0170 struct ds620_data *data = ds620_update_client(dev);
0171 struct i2c_client *client;
0172 u16 conf, new_conf;
0173 int res;
0174
0175 if (IS_ERR(data))
0176 return PTR_ERR(data);
0177
0178 client = data->client;
0179
0180
0181 res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
0182 if (res < 0)
0183 return res;
0184
0185 new_conf = conf = res;
0186 new_conf &= ~attr->index;
0187 if (conf != new_conf) {
0188 res = i2c_smbus_write_word_swapped(client, DS620_REG_CONF,
0189 new_conf);
0190 if (res < 0)
0191 return res;
0192 }
0193
0194 return sprintf(buf, "%d\n", !!(conf & attr->index));
0195 }
0196
0197 static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
0198 static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, 1);
0199 static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 2);
0200 static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, DS620_REG_CONFIG_TLF);
0201 static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, DS620_REG_CONFIG_THF);
0202
0203 static struct attribute *ds620_attrs[] = {
0204 &sensor_dev_attr_temp1_input.dev_attr.attr,
0205 &sensor_dev_attr_temp1_min.dev_attr.attr,
0206 &sensor_dev_attr_temp1_max.dev_attr.attr,
0207 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
0208 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
0209 NULL
0210 };
0211
0212 ATTRIBUTE_GROUPS(ds620);
0213
0214 static int ds620_probe(struct i2c_client *client)
0215 {
0216 struct device *dev = &client->dev;
0217 struct device *hwmon_dev;
0218 struct ds620_data *data;
0219
0220 data = devm_kzalloc(dev, sizeof(struct ds620_data), GFP_KERNEL);
0221 if (!data)
0222 return -ENOMEM;
0223
0224 data->client = client;
0225 mutex_init(&data->update_lock);
0226
0227
0228 ds620_init_client(client);
0229
0230 hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
0231 data, ds620_groups);
0232 return PTR_ERR_OR_ZERO(hwmon_dev);
0233 }
0234
0235 static const struct i2c_device_id ds620_id[] = {
0236 {"ds620", 0},
0237 {}
0238 };
0239
0240 MODULE_DEVICE_TABLE(i2c, ds620_id);
0241
0242
0243 static struct i2c_driver ds620_driver = {
0244 .class = I2C_CLASS_HWMON,
0245 .driver = {
0246 .name = "ds620",
0247 },
0248 .probe_new = ds620_probe,
0249 .id_table = ds620_id,
0250 };
0251
0252 module_i2c_driver(ds620_driver);
0253
0254 MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
0255 MODULE_DESCRIPTION("DS620 driver");
0256 MODULE_LICENSE("GPL");