diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2007-09-09 13:51:14 -0400 |
---|---|---|
committer | Mark M. Hoffman <mhoffman@lightlink.com> | 2007-10-09 22:56:31 -0400 |
commit | a8d6646e24fa72de38de5838df8bd1f21af59710 (patch) | |
tree | 61ebbed4ea0f7d693ed92a77a592cd4ea7892fae | |
parent | bba891c24a77419e9dcf76f866bd0d8ecf66d770 (diff) |
hwmon: (adm1021) dynamic sysfs callbacks conversion
This is conversion of the driver to the dynamic sysfs callbacks.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Acked-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
-rw-r--r-- | drivers/hwmon/adm1021.c | 194 |
1 files changed, 106 insertions, 88 deletions
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 5667630ac05a..cc4097094282 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/hwmon.h> | 27 | #include <linux/hwmon.h> |
28 | #include <linux/hwmon-sysfs.h> | ||
28 | #include <linux/err.h> | 29 | #include <linux/err.h> |
29 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
30 | 31 | ||
@@ -43,8 +44,8 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, | |||
43 | 44 | ||
44 | /* The adm1021 registers */ | 45 | /* The adm1021 registers */ |
45 | /* Read-only */ | 46 | /* Read-only */ |
46 | #define ADM1021_REG_TEMP 0x00 | 47 | /* For nr in 0-1 */ |
47 | #define ADM1021_REG_REMOTE_TEMP 0x01 | 48 | #define ADM1021_REG_TEMP(nr) (nr) |
48 | #define ADM1021_REG_STATUS 0x02 | 49 | #define ADM1021_REG_STATUS 0x02 |
49 | /* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */ | 50 | /* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */ |
50 | #define ADM1021_REG_MAN_ID 0xFE | 51 | #define ADM1021_REG_MAN_ID 0xFE |
@@ -62,25 +63,14 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, | |||
62 | #define ADM1023_REG_REM_TOS_PREC 0x13 | 63 | #define ADM1023_REG_REM_TOS_PREC 0x13 |
63 | #define ADM1023_REG_REM_THYST_PREC 0x14 | 64 | #define ADM1023_REG_REM_THYST_PREC 0x14 |
64 | /* limits */ | 65 | /* limits */ |
65 | #define ADM1021_REG_TOS_R 0x05 | 66 | /* For nr in 0-1 */ |
66 | #define ADM1021_REG_TOS_W 0x0B | 67 | #define ADM1021_REG_TOS_R(nr) (0x05 + 2 * (nr)) |
67 | #define ADM1021_REG_REMOTE_TOS_R 0x07 | 68 | #define ADM1021_REG_TOS_W(nr) (0x0B + 2 * (nr)) |
68 | #define ADM1021_REG_REMOTE_TOS_W 0x0D | 69 | #define ADM1021_REG_THYST_R(nr) (0x06 + 2 * (nr)) |
69 | #define ADM1021_REG_THYST_R 0x06 | 70 | #define ADM1021_REG_THYST_W(nr) (0x0C + 2 * (nr)) |
70 | #define ADM1021_REG_THYST_W 0x0C | ||
71 | #define ADM1021_REG_REMOTE_THYST_R 0x08 | ||
72 | #define ADM1021_REG_REMOTE_THYST_W 0x0E | ||
73 | /* write-only */ | 71 | /* write-only */ |
74 | #define ADM1021_REG_ONESHOT 0x0F | 72 | #define ADM1021_REG_ONESHOT 0x0F |
75 | 73 | ||
76 | |||
77 | /* Conversions. Rounding and limit checking is only done on the TO_REG | ||
78 | variants. Note that you should be a bit careful with which arguments | ||
79 | these macros are called: arguments may be evaluated more than once. | ||
80 | Fixing this is just not worth it. */ | ||
81 | /* Conversions note: 1021 uses normal integer signed-byte format*/ | ||
82 | #define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -128, 127) | ||
83 | |||
84 | /* Initial values */ | 74 | /* Initial values */ |
85 | 75 | ||
86 | /* Note: Even though I left the low and high limits named os and hyst, | 76 | /* Note: Even though I left the low and high limits named os and hyst, |
@@ -98,19 +88,16 @@ struct adm1021_data { | |||
98 | char valid; /* !=0 if following fields are valid */ | 88 | char valid; /* !=0 if following fields are valid */ |
99 | unsigned long last_updated; /* In jiffies */ | 89 | unsigned long last_updated; /* In jiffies */ |
100 | 90 | ||
101 | s8 temp_max; /* Register values */ | 91 | s8 temp_max[2]; /* Register values */ |
102 | s8 temp_hyst; | 92 | s8 temp_min[2]; |
103 | s8 temp_input; | 93 | s8 temp[2]; |
104 | s8 remote_temp_max; | 94 | u8 alarms; |
105 | s8 remote_temp_hyst; | 95 | /* Special values for ADM1023 only */ |
106 | s8 remote_temp_input; | 96 | u8 remote_temp_prec; |
107 | u8 alarms; | 97 | u8 remote_temp_os_prec; |
108 | /* Special values for ADM1023 only */ | 98 | u8 remote_temp_hyst_prec; |
109 | u8 remote_temp_prec; | 99 | u8 remote_temp_offset; |
110 | u8 remote_temp_os_prec; | 100 | u8 remote_temp_offset_prec; |
111 | u8 remote_temp_hyst_prec; | ||
112 | u8 remote_temp_offset; | ||
113 | u8 remote_temp_offset_prec; | ||
114 | }; | 101 | }; |
115 | 102 | ||
116 | static int adm1021_attach_adapter(struct i2c_adapter *adapter); | 103 | static int adm1021_attach_adapter(struct i2c_adapter *adapter); |
@@ -133,19 +120,32 @@ static struct i2c_driver adm1021_driver = { | |||
133 | .detach_client = adm1021_detach_client, | 120 | .detach_client = adm1021_detach_client, |
134 | }; | 121 | }; |
135 | 122 | ||
136 | #define show(value) \ | 123 | static ssize_t show_temp(struct device *dev, |
137 | static ssize_t show_##value(struct device *dev, \ | 124 | struct device_attribute *devattr, char *buf) |
138 | struct device_attribute *attr, char *buf) \ | 125 | { |
139 | { \ | 126 | int index = to_sensor_dev_attr(devattr)->index; |
140 | struct adm1021_data *data = adm1021_update_device(dev); \ | 127 | struct adm1021_data *data = adm1021_update_device(dev); |
141 | return sprintf(buf, "%d\n", 1000 * data->value); \ | 128 | |
129 | return sprintf(buf, "%d\n", 1000 * data->temp[index]); | ||
130 | } | ||
131 | |||
132 | static ssize_t show_temp_max(struct device *dev, | ||
133 | struct device_attribute *devattr, char *buf) | ||
134 | { | ||
135 | int index = to_sensor_dev_attr(devattr)->index; | ||
136 | struct adm1021_data *data = adm1021_update_device(dev); | ||
137 | |||
138 | return sprintf(buf, "%d\n", 1000 * data->temp_max[index]); | ||
139 | } | ||
140 | |||
141 | static ssize_t show_temp_min(struct device *dev, | ||
142 | struct device_attribute *devattr, char *buf) | ||
143 | { | ||
144 | int index = to_sensor_dev_attr(devattr)->index; | ||
145 | struct adm1021_data *data = adm1021_update_device(dev); | ||
146 | |||
147 | return sprintf(buf, "%d\n", 1000 * data->temp_min[index]); | ||
142 | } | 148 | } |
143 | show(temp_max); | ||
144 | show(temp_hyst); | ||
145 | show(temp_input); | ||
146 | show(remote_temp_max); | ||
147 | show(remote_temp_hyst); | ||
148 | show(remote_temp_input); | ||
149 | 149 | ||
150 | static ssize_t show_alarms(struct device *dev, | 150 | static ssize_t show_alarms(struct device *dev, |
151 | struct device_attribute *attr, | 151 | struct device_attribute *attr, |
@@ -155,35 +155,55 @@ static ssize_t show_alarms(struct device *dev, | |||
155 | return sprintf(buf, "%u\n", data->alarms); | 155 | return sprintf(buf, "%u\n", data->alarms); |
156 | } | 156 | } |
157 | 157 | ||
158 | #define set(value, reg) \ | 158 | static ssize_t set_temp_max(struct device *dev, |
159 | static ssize_t set_##value(struct device *dev, \ | 159 | struct device_attribute *devattr, |
160 | struct device_attribute *attr, \ | 160 | const char *buf, size_t count) |
161 | const char *buf, size_t count) \ | 161 | { |
162 | { \ | 162 | int index = to_sensor_dev_attr(devattr)->index; |
163 | struct i2c_client *client = to_i2c_client(dev); \ | 163 | struct i2c_client *client = to_i2c_client(dev); |
164 | struct adm1021_data *data = i2c_get_clientdata(client); \ | 164 | struct adm1021_data *data = i2c_get_clientdata(client); |
165 | long temp = simple_strtol(buf, NULL, 10); \ | 165 | long temp = simple_strtol(buf, NULL, 10) / 1000; |
166 | \ | 166 | |
167 | mutex_lock(&data->update_lock); \ | 167 | mutex_lock(&data->update_lock); |
168 | data->value = TEMP_TO_REG(temp); \ | 168 | data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127); |
169 | if (!read_only) \ | 169 | if (!read_only) |
170 | i2c_smbus_write_byte_data(client, reg, data->value); \ | 170 | i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W(index), |
171 | mutex_unlock(&data->update_lock); \ | 171 | data->temp_max[index]); |
172 | return count; \ | 172 | mutex_unlock(&data->update_lock); |
173 | |||
174 | return count; | ||
173 | } | 175 | } |
174 | set(temp_max, ADM1021_REG_TOS_W); | ||
175 | set(temp_hyst, ADM1021_REG_THYST_W); | ||
176 | set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W); | ||
177 | set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W); | ||
178 | |||
179 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); | ||
180 | static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); | ||
181 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); | ||
182 | static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max); | ||
183 | static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst); | ||
184 | static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL); | ||
185 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | ||
186 | 176 | ||
177 | static ssize_t set_temp_min(struct device *dev, | ||
178 | struct device_attribute *devattr, | ||
179 | const char *buf, size_t count) | ||
180 | { | ||
181 | int index = to_sensor_dev_attr(devattr)->index; | ||
182 | struct i2c_client *client = to_i2c_client(dev); | ||
183 | struct adm1021_data *data = i2c_get_clientdata(client); | ||
184 | long temp = simple_strtol(buf, NULL, 10) / 1000; | ||
185 | |||
186 | mutex_lock(&data->update_lock); | ||
187 | data->temp_min[index] = SENSORS_LIMIT(temp, -128, 127); | ||
188 | if (!read_only) | ||
189 | i2c_smbus_write_byte_data(client, ADM1021_REG_THYST_W(index), | ||
190 | data->temp_min[index]); | ||
191 | mutex_unlock(&data->update_lock); | ||
192 | |||
193 | return count; | ||
194 | } | ||
195 | |||
196 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
197 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
198 | set_temp_max, 0); | ||
199 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
200 | set_temp_min, 0); | ||
201 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
202 | static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
203 | set_temp_max, 1); | ||
204 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
205 | set_temp_min, 1); | ||
206 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | ||
187 | 207 | ||
188 | static int adm1021_attach_adapter(struct i2c_adapter *adapter) | 208 | static int adm1021_attach_adapter(struct i2c_adapter *adapter) |
189 | { | 209 | { |
@@ -193,12 +213,12 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter) | |||
193 | } | 213 | } |
194 | 214 | ||
195 | static struct attribute *adm1021_attributes[] = { | 215 | static struct attribute *adm1021_attributes[] = { |
196 | &dev_attr_temp1_max.attr, | 216 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
197 | &dev_attr_temp1_min.attr, | 217 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
198 | &dev_attr_temp1_input.attr, | 218 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
199 | &dev_attr_temp2_max.attr, | 219 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
200 | &dev_attr_temp2_min.attr, | 220 | &sensor_dev_attr_temp2_min.dev_attr.attr, |
201 | &dev_attr_temp2_input.attr, | 221 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
202 | &dev_attr_alarms.attr, | 222 | &dev_attr_alarms.attr, |
203 | NULL | 223 | NULL |
204 | }; | 224 | }; |
@@ -370,20 +390,18 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) | |||
370 | 390 | ||
371 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 391 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
372 | || !data->valid) { | 392 | || !data->valid) { |
393 | int i; | ||
394 | |||
373 | dev_dbg(&client->dev, "Starting adm1021 update\n"); | 395 | dev_dbg(&client->dev, "Starting adm1021 update\n"); |
374 | 396 | ||
375 | data->temp_input = i2c_smbus_read_byte_data(client, | 397 | for (i = 0; i < 2; i++) { |
376 | ADM1021_REG_TEMP); | 398 | data->temp[i] = i2c_smbus_read_byte_data(client, |
377 | data->temp_max = i2c_smbus_read_byte_data(client, | 399 | ADM1021_REG_TEMP(i)); |
378 | ADM1021_REG_TOS_R); | 400 | data->temp_max[i] = i2c_smbus_read_byte_data(client, |
379 | data->temp_hyst = i2c_smbus_read_byte_data(client, | 401 | ADM1021_REG_TOS_R(i)); |
380 | ADM1021_REG_THYST_R); | 402 | data->temp_min[i] = i2c_smbus_read_byte_data(client, |
381 | data->remote_temp_input = i2c_smbus_read_byte_data(client, | 403 | ADM1021_REG_THYST_R(i)); |
382 | ADM1021_REG_REMOTE_TEMP); | 404 | } |
383 | data->remote_temp_max = i2c_smbus_read_byte_data(client, | ||
384 | ADM1021_REG_REMOTE_TOS_R); | ||
385 | data->remote_temp_hyst = i2c_smbus_read_byte_data(client, | ||
386 | ADM1021_REG_REMOTE_THYST_R); | ||
387 | data->alarms = i2c_smbus_read_byte_data(client, | 405 | data->alarms = i2c_smbus_read_byte_data(client, |
388 | ADM1021_REG_STATUS) & 0x7c; | 406 | ADM1021_REG_STATUS) & 0x7c; |
389 | if (data->type == adm1023) { | 407 | if (data->type == adm1023) { |