Commit f9286434ea64803b673bb4ec0dd7084b13c2d90b
1 parent
9cc7dcc523
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
hwmon: (amc6821) Convert to use devm_ functions
Convert to use devm_ functions to reduce code size and simplify the code. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Showing 1 changed file with 5 additions and 11 deletions Inline Diff
drivers/hwmon/amc6821.c
1 | /* | 1 | /* |
2 | * amc6821.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * amc6821.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | * monitoring | 3 | * monitoring |
4 | * Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si> | 4 | * Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si> |
5 | * | 5 | * |
6 | * Based on max6650.c: | 6 | * Based on max6650.c: |
7 | * Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de> | 7 | * Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or | 11 | * the Free Software Foundation; either version 2 of the License, or |
12 | * (at your option) any later version. | 12 | * (at your option) any later version. |
13 | * | 13 | * |
14 | * This program is distributed in the hope that it will be useful, | 14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. | 17 | * GNU General Public License for more details. |
18 | * | 18 | * |
19 | * You should have received a copy of the GNU General Public License | 19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | 24 | ||
25 | #include <linux/kernel.h> /* Needed for KERN_INFO */ | 25 | #include <linux/kernel.h> /* Needed for KERN_INFO */ |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/jiffies.h> | 29 | #include <linux/jiffies.h> |
30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
31 | #include <linux/hwmon.h> | 31 | #include <linux/hwmon.h> |
32 | #include <linux/hwmon-sysfs.h> | 32 | #include <linux/hwmon-sysfs.h> |
33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | 35 | ||
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Addresses to scan. | 38 | * Addresses to scan. |
39 | */ | 39 | */ |
40 | 40 | ||
41 | static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, | 41 | static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, |
42 | 0x4c, 0x4d, 0x4e, I2C_CLIENT_END}; | 42 | 0x4c, 0x4d, 0x4e, I2C_CLIENT_END}; |
43 | 43 | ||
44 | 44 | ||
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Insmod parameters | 47 | * Insmod parameters |
48 | */ | 48 | */ |
49 | 49 | ||
50 | static int pwminv; /*Inverted PWM output. */ | 50 | static int pwminv; /*Inverted PWM output. */ |
51 | module_param(pwminv, int, S_IRUGO); | 51 | module_param(pwminv, int, S_IRUGO); |
52 | 52 | ||
53 | static int init = 1; /*Power-on initialization.*/ | 53 | static int init = 1; /*Power-on initialization.*/ |
54 | module_param(init, int, S_IRUGO); | 54 | module_param(init, int, S_IRUGO); |
55 | 55 | ||
56 | 56 | ||
57 | enum chips { amc6821 }; | 57 | enum chips { amc6821 }; |
58 | 58 | ||
59 | #define AMC6821_REG_DEV_ID 0x3D | 59 | #define AMC6821_REG_DEV_ID 0x3D |
60 | #define AMC6821_REG_COMP_ID 0x3E | 60 | #define AMC6821_REG_COMP_ID 0x3E |
61 | #define AMC6821_REG_CONF1 0x00 | 61 | #define AMC6821_REG_CONF1 0x00 |
62 | #define AMC6821_REG_CONF2 0x01 | 62 | #define AMC6821_REG_CONF2 0x01 |
63 | #define AMC6821_REG_CONF3 0x3F | 63 | #define AMC6821_REG_CONF3 0x3F |
64 | #define AMC6821_REG_CONF4 0x04 | 64 | #define AMC6821_REG_CONF4 0x04 |
65 | #define AMC6821_REG_STAT1 0x02 | 65 | #define AMC6821_REG_STAT1 0x02 |
66 | #define AMC6821_REG_STAT2 0x03 | 66 | #define AMC6821_REG_STAT2 0x03 |
67 | #define AMC6821_REG_TDATA_LOW 0x08 | 67 | #define AMC6821_REG_TDATA_LOW 0x08 |
68 | #define AMC6821_REG_TDATA_HI 0x09 | 68 | #define AMC6821_REG_TDATA_HI 0x09 |
69 | #define AMC6821_REG_LTEMP_HI 0x0A | 69 | #define AMC6821_REG_LTEMP_HI 0x0A |
70 | #define AMC6821_REG_RTEMP_HI 0x0B | 70 | #define AMC6821_REG_RTEMP_HI 0x0B |
71 | #define AMC6821_REG_LTEMP_LIMIT_MIN 0x15 | 71 | #define AMC6821_REG_LTEMP_LIMIT_MIN 0x15 |
72 | #define AMC6821_REG_LTEMP_LIMIT_MAX 0x14 | 72 | #define AMC6821_REG_LTEMP_LIMIT_MAX 0x14 |
73 | #define AMC6821_REG_RTEMP_LIMIT_MIN 0x19 | 73 | #define AMC6821_REG_RTEMP_LIMIT_MIN 0x19 |
74 | #define AMC6821_REG_RTEMP_LIMIT_MAX 0x18 | 74 | #define AMC6821_REG_RTEMP_LIMIT_MAX 0x18 |
75 | #define AMC6821_REG_LTEMP_CRIT 0x1B | 75 | #define AMC6821_REG_LTEMP_CRIT 0x1B |
76 | #define AMC6821_REG_RTEMP_CRIT 0x1D | 76 | #define AMC6821_REG_RTEMP_CRIT 0x1D |
77 | #define AMC6821_REG_PSV_TEMP 0x1C | 77 | #define AMC6821_REG_PSV_TEMP 0x1C |
78 | #define AMC6821_REG_DCY 0x22 | 78 | #define AMC6821_REG_DCY 0x22 |
79 | #define AMC6821_REG_LTEMP_FAN_CTRL 0x24 | 79 | #define AMC6821_REG_LTEMP_FAN_CTRL 0x24 |
80 | #define AMC6821_REG_RTEMP_FAN_CTRL 0x25 | 80 | #define AMC6821_REG_RTEMP_FAN_CTRL 0x25 |
81 | #define AMC6821_REG_DCY_LOW_TEMP 0x21 | 81 | #define AMC6821_REG_DCY_LOW_TEMP 0x21 |
82 | 82 | ||
83 | #define AMC6821_REG_TACH_LLIMITL 0x10 | 83 | #define AMC6821_REG_TACH_LLIMITL 0x10 |
84 | #define AMC6821_REG_TACH_LLIMITH 0x11 | 84 | #define AMC6821_REG_TACH_LLIMITH 0x11 |
85 | #define AMC6821_REG_TACH_HLIMITL 0x12 | 85 | #define AMC6821_REG_TACH_HLIMITL 0x12 |
86 | #define AMC6821_REG_TACH_HLIMITH 0x13 | 86 | #define AMC6821_REG_TACH_HLIMITH 0x13 |
87 | 87 | ||
88 | #define AMC6821_CONF1_START 0x01 | 88 | #define AMC6821_CONF1_START 0x01 |
89 | #define AMC6821_CONF1_FAN_INT_EN 0x02 | 89 | #define AMC6821_CONF1_FAN_INT_EN 0x02 |
90 | #define AMC6821_CONF1_FANIE 0x04 | 90 | #define AMC6821_CONF1_FANIE 0x04 |
91 | #define AMC6821_CONF1_PWMINV 0x08 | 91 | #define AMC6821_CONF1_PWMINV 0x08 |
92 | #define AMC6821_CONF1_FAN_FAULT_EN 0x10 | 92 | #define AMC6821_CONF1_FAN_FAULT_EN 0x10 |
93 | #define AMC6821_CONF1_FDRC0 0x20 | 93 | #define AMC6821_CONF1_FDRC0 0x20 |
94 | #define AMC6821_CONF1_FDRC1 0x40 | 94 | #define AMC6821_CONF1_FDRC1 0x40 |
95 | #define AMC6821_CONF1_THERMOVIE 0x80 | 95 | #define AMC6821_CONF1_THERMOVIE 0x80 |
96 | 96 | ||
97 | #define AMC6821_CONF2_PWM_EN 0x01 | 97 | #define AMC6821_CONF2_PWM_EN 0x01 |
98 | #define AMC6821_CONF2_TACH_MODE 0x02 | 98 | #define AMC6821_CONF2_TACH_MODE 0x02 |
99 | #define AMC6821_CONF2_TACH_EN 0x04 | 99 | #define AMC6821_CONF2_TACH_EN 0x04 |
100 | #define AMC6821_CONF2_RTFIE 0x08 | 100 | #define AMC6821_CONF2_RTFIE 0x08 |
101 | #define AMC6821_CONF2_LTOIE 0x10 | 101 | #define AMC6821_CONF2_LTOIE 0x10 |
102 | #define AMC6821_CONF2_RTOIE 0x20 | 102 | #define AMC6821_CONF2_RTOIE 0x20 |
103 | #define AMC6821_CONF2_PSVIE 0x40 | 103 | #define AMC6821_CONF2_PSVIE 0x40 |
104 | #define AMC6821_CONF2_RST 0x80 | 104 | #define AMC6821_CONF2_RST 0x80 |
105 | 105 | ||
106 | #define AMC6821_CONF3_THERM_FAN_EN 0x80 | 106 | #define AMC6821_CONF3_THERM_FAN_EN 0x80 |
107 | #define AMC6821_CONF3_REV_MASK 0x0F | 107 | #define AMC6821_CONF3_REV_MASK 0x0F |
108 | 108 | ||
109 | #define AMC6821_CONF4_OVREN 0x10 | 109 | #define AMC6821_CONF4_OVREN 0x10 |
110 | #define AMC6821_CONF4_TACH_FAST 0x20 | 110 | #define AMC6821_CONF4_TACH_FAST 0x20 |
111 | #define AMC6821_CONF4_PSPR 0x40 | 111 | #define AMC6821_CONF4_PSPR 0x40 |
112 | #define AMC6821_CONF4_MODE 0x80 | 112 | #define AMC6821_CONF4_MODE 0x80 |
113 | 113 | ||
114 | #define AMC6821_STAT1_RPM_ALARM 0x01 | 114 | #define AMC6821_STAT1_RPM_ALARM 0x01 |
115 | #define AMC6821_STAT1_FANS 0x02 | 115 | #define AMC6821_STAT1_FANS 0x02 |
116 | #define AMC6821_STAT1_RTH 0x04 | 116 | #define AMC6821_STAT1_RTH 0x04 |
117 | #define AMC6821_STAT1_RTL 0x08 | 117 | #define AMC6821_STAT1_RTL 0x08 |
118 | #define AMC6821_STAT1_R_THERM 0x10 | 118 | #define AMC6821_STAT1_R_THERM 0x10 |
119 | #define AMC6821_STAT1_RTF 0x20 | 119 | #define AMC6821_STAT1_RTF 0x20 |
120 | #define AMC6821_STAT1_LTH 0x40 | 120 | #define AMC6821_STAT1_LTH 0x40 |
121 | #define AMC6821_STAT1_LTL 0x80 | 121 | #define AMC6821_STAT1_LTL 0x80 |
122 | 122 | ||
123 | #define AMC6821_STAT2_RTC 0x08 | 123 | #define AMC6821_STAT2_RTC 0x08 |
124 | #define AMC6821_STAT2_LTC 0x10 | 124 | #define AMC6821_STAT2_LTC 0x10 |
125 | #define AMC6821_STAT2_LPSV 0x20 | 125 | #define AMC6821_STAT2_LPSV 0x20 |
126 | #define AMC6821_STAT2_L_THERM 0x40 | 126 | #define AMC6821_STAT2_L_THERM 0x40 |
127 | #define AMC6821_STAT2_THERM_IN 0x80 | 127 | #define AMC6821_STAT2_THERM_IN 0x80 |
128 | 128 | ||
129 | enum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX, | 129 | enum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX, |
130 | IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN, | 130 | IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN, |
131 | IDX_TEMP2_MAX, IDX_TEMP2_CRIT, | 131 | IDX_TEMP2_MAX, IDX_TEMP2_CRIT, |
132 | TEMP_IDX_LEN, }; | 132 | TEMP_IDX_LEN, }; |
133 | 133 | ||
134 | static const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI, | 134 | static const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI, |
135 | AMC6821_REG_LTEMP_LIMIT_MIN, | 135 | AMC6821_REG_LTEMP_LIMIT_MIN, |
136 | AMC6821_REG_LTEMP_LIMIT_MAX, | 136 | AMC6821_REG_LTEMP_LIMIT_MAX, |
137 | AMC6821_REG_LTEMP_CRIT, | 137 | AMC6821_REG_LTEMP_CRIT, |
138 | AMC6821_REG_RTEMP_HI, | 138 | AMC6821_REG_RTEMP_HI, |
139 | AMC6821_REG_RTEMP_LIMIT_MIN, | 139 | AMC6821_REG_RTEMP_LIMIT_MIN, |
140 | AMC6821_REG_RTEMP_LIMIT_MAX, | 140 | AMC6821_REG_RTEMP_LIMIT_MAX, |
141 | AMC6821_REG_RTEMP_CRIT, }; | 141 | AMC6821_REG_RTEMP_CRIT, }; |
142 | 142 | ||
143 | enum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX, | 143 | enum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX, |
144 | FAN1_IDX_LEN, }; | 144 | FAN1_IDX_LEN, }; |
145 | 145 | ||
146 | static const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW, | 146 | static const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW, |
147 | AMC6821_REG_TACH_LLIMITL, | 147 | AMC6821_REG_TACH_LLIMITL, |
148 | AMC6821_REG_TACH_HLIMITL, }; | 148 | AMC6821_REG_TACH_HLIMITL, }; |
149 | 149 | ||
150 | 150 | ||
151 | static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, | 151 | static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, |
152 | AMC6821_REG_TACH_LLIMITH, | 152 | AMC6821_REG_TACH_LLIMITH, |
153 | AMC6821_REG_TACH_HLIMITH, }; | 153 | AMC6821_REG_TACH_HLIMITH, }; |
154 | 154 | ||
155 | static int amc6821_probe( | 155 | static int amc6821_probe( |
156 | struct i2c_client *client, | 156 | struct i2c_client *client, |
157 | const struct i2c_device_id *id); | 157 | const struct i2c_device_id *id); |
158 | static int amc6821_detect( | 158 | static int amc6821_detect( |
159 | struct i2c_client *client, | 159 | struct i2c_client *client, |
160 | struct i2c_board_info *info); | 160 | struct i2c_board_info *info); |
161 | static int amc6821_init_client(struct i2c_client *client); | 161 | static int amc6821_init_client(struct i2c_client *client); |
162 | static int amc6821_remove(struct i2c_client *client); | 162 | static int amc6821_remove(struct i2c_client *client); |
163 | static struct amc6821_data *amc6821_update_device(struct device *dev); | 163 | static struct amc6821_data *amc6821_update_device(struct device *dev); |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * Driver data (common to all clients) | 166 | * Driver data (common to all clients) |
167 | */ | 167 | */ |
168 | 168 | ||
169 | static const struct i2c_device_id amc6821_id[] = { | 169 | static const struct i2c_device_id amc6821_id[] = { |
170 | { "amc6821", amc6821 }, | 170 | { "amc6821", amc6821 }, |
171 | { } | 171 | { } |
172 | }; | 172 | }; |
173 | 173 | ||
174 | MODULE_DEVICE_TABLE(i2c, amc6821_id); | 174 | MODULE_DEVICE_TABLE(i2c, amc6821_id); |
175 | 175 | ||
176 | static struct i2c_driver amc6821_driver = { | 176 | static struct i2c_driver amc6821_driver = { |
177 | .class = I2C_CLASS_HWMON, | 177 | .class = I2C_CLASS_HWMON, |
178 | .driver = { | 178 | .driver = { |
179 | .name = "amc6821", | 179 | .name = "amc6821", |
180 | }, | 180 | }, |
181 | .probe = amc6821_probe, | 181 | .probe = amc6821_probe, |
182 | .remove = amc6821_remove, | 182 | .remove = amc6821_remove, |
183 | .id_table = amc6821_id, | 183 | .id_table = amc6821_id, |
184 | .detect = amc6821_detect, | 184 | .detect = amc6821_detect, |
185 | .address_list = normal_i2c, | 185 | .address_list = normal_i2c, |
186 | }; | 186 | }; |
187 | 187 | ||
188 | 188 | ||
189 | /* | 189 | /* |
190 | * Client data (each client gets its own) | 190 | * Client data (each client gets its own) |
191 | */ | 191 | */ |
192 | 192 | ||
193 | struct amc6821_data { | 193 | struct amc6821_data { |
194 | struct device *hwmon_dev; | 194 | struct device *hwmon_dev; |
195 | struct mutex update_lock; | 195 | struct mutex update_lock; |
196 | char valid; /* zero until following fields are valid */ | 196 | char valid; /* zero until following fields are valid */ |
197 | unsigned long last_updated; /* in jiffies */ | 197 | unsigned long last_updated; /* in jiffies */ |
198 | 198 | ||
199 | /* register values */ | 199 | /* register values */ |
200 | int temp[TEMP_IDX_LEN]; | 200 | int temp[TEMP_IDX_LEN]; |
201 | 201 | ||
202 | u16 fan[FAN1_IDX_LEN]; | 202 | u16 fan[FAN1_IDX_LEN]; |
203 | u8 fan1_div; | 203 | u8 fan1_div; |
204 | 204 | ||
205 | u8 pwm1; | 205 | u8 pwm1; |
206 | u8 temp1_auto_point_temp[3]; | 206 | u8 temp1_auto_point_temp[3]; |
207 | u8 temp2_auto_point_temp[3]; | 207 | u8 temp2_auto_point_temp[3]; |
208 | u8 pwm1_auto_point_pwm[3]; | 208 | u8 pwm1_auto_point_pwm[3]; |
209 | u8 pwm1_enable; | 209 | u8 pwm1_enable; |
210 | u8 pwm1_auto_channels_temp; | 210 | u8 pwm1_auto_channels_temp; |
211 | 211 | ||
212 | u8 stat1; | 212 | u8 stat1; |
213 | u8 stat2; | 213 | u8 stat2; |
214 | }; | 214 | }; |
215 | 215 | ||
216 | 216 | ||
217 | static ssize_t get_temp( | 217 | static ssize_t get_temp( |
218 | struct device *dev, | 218 | struct device *dev, |
219 | struct device_attribute *devattr, | 219 | struct device_attribute *devattr, |
220 | char *buf) | 220 | char *buf) |
221 | { | 221 | { |
222 | struct amc6821_data *data = amc6821_update_device(dev); | 222 | struct amc6821_data *data = amc6821_update_device(dev); |
223 | int ix = to_sensor_dev_attr(devattr)->index; | 223 | int ix = to_sensor_dev_attr(devattr)->index; |
224 | 224 | ||
225 | return sprintf(buf, "%d\n", data->temp[ix] * 1000); | 225 | return sprintf(buf, "%d\n", data->temp[ix] * 1000); |
226 | } | 226 | } |
227 | 227 | ||
228 | 228 | ||
229 | 229 | ||
230 | static ssize_t set_temp( | 230 | static ssize_t set_temp( |
231 | struct device *dev, | 231 | struct device *dev, |
232 | struct device_attribute *attr, | 232 | struct device_attribute *attr, |
233 | const char *buf, | 233 | const char *buf, |
234 | size_t count) | 234 | size_t count) |
235 | { | 235 | { |
236 | struct i2c_client *client = to_i2c_client(dev); | 236 | struct i2c_client *client = to_i2c_client(dev); |
237 | struct amc6821_data *data = i2c_get_clientdata(client); | 237 | struct amc6821_data *data = i2c_get_clientdata(client); |
238 | int ix = to_sensor_dev_attr(attr)->index; | 238 | int ix = to_sensor_dev_attr(attr)->index; |
239 | long val; | 239 | long val; |
240 | 240 | ||
241 | int ret = kstrtol(buf, 10, &val); | 241 | int ret = kstrtol(buf, 10, &val); |
242 | if (ret) | 242 | if (ret) |
243 | return ret; | 243 | return ret; |
244 | val = SENSORS_LIMIT(val / 1000, -128, 127); | 244 | val = SENSORS_LIMIT(val / 1000, -128, 127); |
245 | 245 | ||
246 | mutex_lock(&data->update_lock); | 246 | mutex_lock(&data->update_lock); |
247 | data->temp[ix] = val; | 247 | data->temp[ix] = val; |
248 | if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) { | 248 | if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) { |
249 | dev_err(&client->dev, "Register write error, aborting.\n"); | 249 | dev_err(&client->dev, "Register write error, aborting.\n"); |
250 | count = -EIO; | 250 | count = -EIO; |
251 | } | 251 | } |
252 | mutex_unlock(&data->update_lock); | 252 | mutex_unlock(&data->update_lock); |
253 | return count; | 253 | return count; |
254 | } | 254 | } |
255 | 255 | ||
256 | 256 | ||
257 | 257 | ||
258 | 258 | ||
259 | static ssize_t get_temp_alarm( | 259 | static ssize_t get_temp_alarm( |
260 | struct device *dev, | 260 | struct device *dev, |
261 | struct device_attribute *devattr, | 261 | struct device_attribute *devattr, |
262 | char *buf) | 262 | char *buf) |
263 | { | 263 | { |
264 | struct amc6821_data *data = amc6821_update_device(dev); | 264 | struct amc6821_data *data = amc6821_update_device(dev); |
265 | int ix = to_sensor_dev_attr(devattr)->index; | 265 | int ix = to_sensor_dev_attr(devattr)->index; |
266 | u8 flag; | 266 | u8 flag; |
267 | 267 | ||
268 | switch (ix) { | 268 | switch (ix) { |
269 | case IDX_TEMP1_MIN: | 269 | case IDX_TEMP1_MIN: |
270 | flag = data->stat1 & AMC6821_STAT1_LTL; | 270 | flag = data->stat1 & AMC6821_STAT1_LTL; |
271 | break; | 271 | break; |
272 | case IDX_TEMP1_MAX: | 272 | case IDX_TEMP1_MAX: |
273 | flag = data->stat1 & AMC6821_STAT1_LTH; | 273 | flag = data->stat1 & AMC6821_STAT1_LTH; |
274 | break; | 274 | break; |
275 | case IDX_TEMP1_CRIT: | 275 | case IDX_TEMP1_CRIT: |
276 | flag = data->stat2 & AMC6821_STAT2_LTC; | 276 | flag = data->stat2 & AMC6821_STAT2_LTC; |
277 | break; | 277 | break; |
278 | case IDX_TEMP2_MIN: | 278 | case IDX_TEMP2_MIN: |
279 | flag = data->stat1 & AMC6821_STAT1_RTL; | 279 | flag = data->stat1 & AMC6821_STAT1_RTL; |
280 | break; | 280 | break; |
281 | case IDX_TEMP2_MAX: | 281 | case IDX_TEMP2_MAX: |
282 | flag = data->stat1 & AMC6821_STAT1_RTH; | 282 | flag = data->stat1 & AMC6821_STAT1_RTH; |
283 | break; | 283 | break; |
284 | case IDX_TEMP2_CRIT: | 284 | case IDX_TEMP2_CRIT: |
285 | flag = data->stat2 & AMC6821_STAT2_RTC; | 285 | flag = data->stat2 & AMC6821_STAT2_RTC; |
286 | break; | 286 | break; |
287 | default: | 287 | default: |
288 | dev_dbg(dev, "Unknown attr->index (%d).\n", ix); | 288 | dev_dbg(dev, "Unknown attr->index (%d).\n", ix); |
289 | return -EINVAL; | 289 | return -EINVAL; |
290 | } | 290 | } |
291 | if (flag) | 291 | if (flag) |
292 | return sprintf(buf, "1"); | 292 | return sprintf(buf, "1"); |
293 | else | 293 | else |
294 | return sprintf(buf, "0"); | 294 | return sprintf(buf, "0"); |
295 | } | 295 | } |
296 | 296 | ||
297 | 297 | ||
298 | 298 | ||
299 | 299 | ||
300 | static ssize_t get_temp2_fault( | 300 | static ssize_t get_temp2_fault( |
301 | struct device *dev, | 301 | struct device *dev, |
302 | struct device_attribute *devattr, | 302 | struct device_attribute *devattr, |
303 | char *buf) | 303 | char *buf) |
304 | { | 304 | { |
305 | struct amc6821_data *data = amc6821_update_device(dev); | 305 | struct amc6821_data *data = amc6821_update_device(dev); |
306 | if (data->stat1 & AMC6821_STAT1_RTF) | 306 | if (data->stat1 & AMC6821_STAT1_RTF) |
307 | return sprintf(buf, "1"); | 307 | return sprintf(buf, "1"); |
308 | else | 308 | else |
309 | return sprintf(buf, "0"); | 309 | return sprintf(buf, "0"); |
310 | } | 310 | } |
311 | 311 | ||
312 | static ssize_t get_pwm1( | 312 | static ssize_t get_pwm1( |
313 | struct device *dev, | 313 | struct device *dev, |
314 | struct device_attribute *devattr, | 314 | struct device_attribute *devattr, |
315 | char *buf) | 315 | char *buf) |
316 | { | 316 | { |
317 | struct amc6821_data *data = amc6821_update_device(dev); | 317 | struct amc6821_data *data = amc6821_update_device(dev); |
318 | return sprintf(buf, "%d\n", data->pwm1); | 318 | return sprintf(buf, "%d\n", data->pwm1); |
319 | } | 319 | } |
320 | 320 | ||
321 | static ssize_t set_pwm1( | 321 | static ssize_t set_pwm1( |
322 | struct device *dev, | 322 | struct device *dev, |
323 | struct device_attribute *devattr, | 323 | struct device_attribute *devattr, |
324 | const char *buf, | 324 | const char *buf, |
325 | size_t count) | 325 | size_t count) |
326 | { | 326 | { |
327 | struct i2c_client *client = to_i2c_client(dev); | 327 | struct i2c_client *client = to_i2c_client(dev); |
328 | struct amc6821_data *data = i2c_get_clientdata(client); | 328 | struct amc6821_data *data = i2c_get_clientdata(client); |
329 | long val; | 329 | long val; |
330 | int ret = kstrtol(buf, 10, &val); | 330 | int ret = kstrtol(buf, 10, &val); |
331 | if (ret) | 331 | if (ret) |
332 | return ret; | 332 | return ret; |
333 | 333 | ||
334 | mutex_lock(&data->update_lock); | 334 | mutex_lock(&data->update_lock); |
335 | data->pwm1 = SENSORS_LIMIT(val , 0, 255); | 335 | data->pwm1 = SENSORS_LIMIT(val , 0, 255); |
336 | i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1); | 336 | i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1); |
337 | mutex_unlock(&data->update_lock); | 337 | mutex_unlock(&data->update_lock); |
338 | return count; | 338 | return count; |
339 | } | 339 | } |
340 | 340 | ||
341 | static ssize_t get_pwm1_enable( | 341 | static ssize_t get_pwm1_enable( |
342 | struct device *dev, | 342 | struct device *dev, |
343 | struct device_attribute *devattr, | 343 | struct device_attribute *devattr, |
344 | char *buf) | 344 | char *buf) |
345 | { | 345 | { |
346 | struct amc6821_data *data = amc6821_update_device(dev); | 346 | struct amc6821_data *data = amc6821_update_device(dev); |
347 | return sprintf(buf, "%d\n", data->pwm1_enable); | 347 | return sprintf(buf, "%d\n", data->pwm1_enable); |
348 | } | 348 | } |
349 | 349 | ||
350 | static ssize_t set_pwm1_enable( | 350 | static ssize_t set_pwm1_enable( |
351 | struct device *dev, | 351 | struct device *dev, |
352 | struct device_attribute *attr, | 352 | struct device_attribute *attr, |
353 | const char *buf, | 353 | const char *buf, |
354 | size_t count) | 354 | size_t count) |
355 | { | 355 | { |
356 | struct i2c_client *client = to_i2c_client(dev); | 356 | struct i2c_client *client = to_i2c_client(dev); |
357 | struct amc6821_data *data = i2c_get_clientdata(client); | 357 | struct amc6821_data *data = i2c_get_clientdata(client); |
358 | long val; | 358 | long val; |
359 | int config = kstrtol(buf, 10, &val); | 359 | int config = kstrtol(buf, 10, &val); |
360 | if (config) | 360 | if (config) |
361 | return config; | 361 | return config; |
362 | 362 | ||
363 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); | 363 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); |
364 | if (config < 0) { | 364 | if (config < 0) { |
365 | dev_err(&client->dev, | 365 | dev_err(&client->dev, |
366 | "Error reading configuration register, aborting.\n"); | 366 | "Error reading configuration register, aborting.\n"); |
367 | return -EIO; | 367 | return -EIO; |
368 | } | 368 | } |
369 | 369 | ||
370 | switch (val) { | 370 | switch (val) { |
371 | case 1: | 371 | case 1: |
372 | config &= ~AMC6821_CONF1_FDRC0; | 372 | config &= ~AMC6821_CONF1_FDRC0; |
373 | config &= ~AMC6821_CONF1_FDRC1; | 373 | config &= ~AMC6821_CONF1_FDRC1; |
374 | break; | 374 | break; |
375 | case 2: | 375 | case 2: |
376 | config &= ~AMC6821_CONF1_FDRC0; | 376 | config &= ~AMC6821_CONF1_FDRC0; |
377 | config |= AMC6821_CONF1_FDRC1; | 377 | config |= AMC6821_CONF1_FDRC1; |
378 | break; | 378 | break; |
379 | case 3: | 379 | case 3: |
380 | config |= AMC6821_CONF1_FDRC0; | 380 | config |= AMC6821_CONF1_FDRC0; |
381 | config |= AMC6821_CONF1_FDRC1; | 381 | config |= AMC6821_CONF1_FDRC1; |
382 | break; | 382 | break; |
383 | default: | 383 | default: |
384 | return -EINVAL; | 384 | return -EINVAL; |
385 | } | 385 | } |
386 | mutex_lock(&data->update_lock); | 386 | mutex_lock(&data->update_lock); |
387 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { | 387 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { |
388 | dev_err(&client->dev, | 388 | dev_err(&client->dev, |
389 | "Configuration register write error, aborting.\n"); | 389 | "Configuration register write error, aborting.\n"); |
390 | count = -EIO; | 390 | count = -EIO; |
391 | } | 391 | } |
392 | mutex_unlock(&data->update_lock); | 392 | mutex_unlock(&data->update_lock); |
393 | return count; | 393 | return count; |
394 | } | 394 | } |
395 | 395 | ||
396 | 396 | ||
397 | static ssize_t get_pwm1_auto_channels_temp( | 397 | static ssize_t get_pwm1_auto_channels_temp( |
398 | struct device *dev, | 398 | struct device *dev, |
399 | struct device_attribute *devattr, | 399 | struct device_attribute *devattr, |
400 | char *buf) | 400 | char *buf) |
401 | { | 401 | { |
402 | struct amc6821_data *data = amc6821_update_device(dev); | 402 | struct amc6821_data *data = amc6821_update_device(dev); |
403 | return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp); | 403 | return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp); |
404 | } | 404 | } |
405 | 405 | ||
406 | 406 | ||
407 | static ssize_t get_temp_auto_point_temp( | 407 | static ssize_t get_temp_auto_point_temp( |
408 | struct device *dev, | 408 | struct device *dev, |
409 | struct device_attribute *devattr, | 409 | struct device_attribute *devattr, |
410 | char *buf) | 410 | char *buf) |
411 | { | 411 | { |
412 | int ix = to_sensor_dev_attr_2(devattr)->index; | 412 | int ix = to_sensor_dev_attr_2(devattr)->index; |
413 | int nr = to_sensor_dev_attr_2(devattr)->nr; | 413 | int nr = to_sensor_dev_attr_2(devattr)->nr; |
414 | struct amc6821_data *data = amc6821_update_device(dev); | 414 | struct amc6821_data *data = amc6821_update_device(dev); |
415 | switch (nr) { | 415 | switch (nr) { |
416 | case 1: | 416 | case 1: |
417 | return sprintf(buf, "%d\n", | 417 | return sprintf(buf, "%d\n", |
418 | data->temp1_auto_point_temp[ix] * 1000); | 418 | data->temp1_auto_point_temp[ix] * 1000); |
419 | break; | 419 | break; |
420 | case 2: | 420 | case 2: |
421 | return sprintf(buf, "%d\n", | 421 | return sprintf(buf, "%d\n", |
422 | data->temp2_auto_point_temp[ix] * 1000); | 422 | data->temp2_auto_point_temp[ix] * 1000); |
423 | break; | 423 | break; |
424 | default: | 424 | default: |
425 | dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); | 425 | dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); |
426 | return -EINVAL; | 426 | return -EINVAL; |
427 | } | 427 | } |
428 | } | 428 | } |
429 | 429 | ||
430 | 430 | ||
431 | static ssize_t get_pwm1_auto_point_pwm( | 431 | static ssize_t get_pwm1_auto_point_pwm( |
432 | struct device *dev, | 432 | struct device *dev, |
433 | struct device_attribute *devattr, | 433 | struct device_attribute *devattr, |
434 | char *buf) | 434 | char *buf) |
435 | { | 435 | { |
436 | int ix = to_sensor_dev_attr(devattr)->index; | 436 | int ix = to_sensor_dev_attr(devattr)->index; |
437 | struct amc6821_data *data = amc6821_update_device(dev); | 437 | struct amc6821_data *data = amc6821_update_device(dev); |
438 | return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]); | 438 | return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]); |
439 | } | 439 | } |
440 | 440 | ||
441 | 441 | ||
442 | static inline ssize_t set_slope_register(struct i2c_client *client, | 442 | static inline ssize_t set_slope_register(struct i2c_client *client, |
443 | u8 reg, | 443 | u8 reg, |
444 | u8 dpwm, | 444 | u8 dpwm, |
445 | u8 *ptemp) | 445 | u8 *ptemp) |
446 | { | 446 | { |
447 | int dt; | 447 | int dt; |
448 | u8 tmp; | 448 | u8 tmp; |
449 | 449 | ||
450 | dt = ptemp[2]-ptemp[1]; | 450 | dt = ptemp[2]-ptemp[1]; |
451 | for (tmp = 4; tmp > 0; tmp--) { | 451 | for (tmp = 4; tmp > 0; tmp--) { |
452 | if (dt * (0x20 >> tmp) >= dpwm) | 452 | if (dt * (0x20 >> tmp) >= dpwm) |
453 | break; | 453 | break; |
454 | } | 454 | } |
455 | tmp |= (ptemp[1] & 0x7C) << 1; | 455 | tmp |= (ptemp[1] & 0x7C) << 1; |
456 | if (i2c_smbus_write_byte_data(client, | 456 | if (i2c_smbus_write_byte_data(client, |
457 | reg, tmp)) { | 457 | reg, tmp)) { |
458 | dev_err(&client->dev, "Register write error, aborting.\n"); | 458 | dev_err(&client->dev, "Register write error, aborting.\n"); |
459 | return -EIO; | 459 | return -EIO; |
460 | } | 460 | } |
461 | return 0; | 461 | return 0; |
462 | } | 462 | } |
463 | 463 | ||
464 | 464 | ||
465 | 465 | ||
466 | static ssize_t set_temp_auto_point_temp( | 466 | static ssize_t set_temp_auto_point_temp( |
467 | struct device *dev, | 467 | struct device *dev, |
468 | struct device_attribute *attr, | 468 | struct device_attribute *attr, |
469 | const char *buf, | 469 | const char *buf, |
470 | size_t count) | 470 | size_t count) |
471 | { | 471 | { |
472 | struct i2c_client *client = to_i2c_client(dev); | 472 | struct i2c_client *client = to_i2c_client(dev); |
473 | struct amc6821_data *data = amc6821_update_device(dev); | 473 | struct amc6821_data *data = amc6821_update_device(dev); |
474 | int ix = to_sensor_dev_attr_2(attr)->index; | 474 | int ix = to_sensor_dev_attr_2(attr)->index; |
475 | int nr = to_sensor_dev_attr_2(attr)->nr; | 475 | int nr = to_sensor_dev_attr_2(attr)->nr; |
476 | u8 *ptemp; | 476 | u8 *ptemp; |
477 | u8 reg; | 477 | u8 reg; |
478 | int dpwm; | 478 | int dpwm; |
479 | long val; | 479 | long val; |
480 | int ret = kstrtol(buf, 10, &val); | 480 | int ret = kstrtol(buf, 10, &val); |
481 | if (ret) | 481 | if (ret) |
482 | return ret; | 482 | return ret; |
483 | 483 | ||
484 | switch (nr) { | 484 | switch (nr) { |
485 | case 1: | 485 | case 1: |
486 | ptemp = data->temp1_auto_point_temp; | 486 | ptemp = data->temp1_auto_point_temp; |
487 | reg = AMC6821_REG_LTEMP_FAN_CTRL; | 487 | reg = AMC6821_REG_LTEMP_FAN_CTRL; |
488 | break; | 488 | break; |
489 | case 2: | 489 | case 2: |
490 | ptemp = data->temp2_auto_point_temp; | 490 | ptemp = data->temp2_auto_point_temp; |
491 | reg = AMC6821_REG_RTEMP_FAN_CTRL; | 491 | reg = AMC6821_REG_RTEMP_FAN_CTRL; |
492 | break; | 492 | break; |
493 | default: | 493 | default: |
494 | dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); | 494 | dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); |
495 | return -EINVAL; | 495 | return -EINVAL; |
496 | } | 496 | } |
497 | 497 | ||
498 | data->valid = 0; | 498 | data->valid = 0; |
499 | mutex_lock(&data->update_lock); | 499 | mutex_lock(&data->update_lock); |
500 | switch (ix) { | 500 | switch (ix) { |
501 | case 0: | 501 | case 0: |
502 | ptemp[0] = SENSORS_LIMIT(val / 1000, 0, | 502 | ptemp[0] = SENSORS_LIMIT(val / 1000, 0, |
503 | data->temp1_auto_point_temp[1]); | 503 | data->temp1_auto_point_temp[1]); |
504 | ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, | 504 | ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, |
505 | data->temp2_auto_point_temp[1]); | 505 | data->temp2_auto_point_temp[1]); |
506 | ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63); | 506 | ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63); |
507 | if (i2c_smbus_write_byte_data( | 507 | if (i2c_smbus_write_byte_data( |
508 | client, | 508 | client, |
509 | AMC6821_REG_PSV_TEMP, | 509 | AMC6821_REG_PSV_TEMP, |
510 | ptemp[0])) { | 510 | ptemp[0])) { |
511 | dev_err(&client->dev, | 511 | dev_err(&client->dev, |
512 | "Register write error, aborting.\n"); | 512 | "Register write error, aborting.\n"); |
513 | count = -EIO; | 513 | count = -EIO; |
514 | } | 514 | } |
515 | goto EXIT; | 515 | goto EXIT; |
516 | break; | 516 | break; |
517 | case 1: | 517 | case 1: |
518 | ptemp[1] = SENSORS_LIMIT( | 518 | ptemp[1] = SENSORS_LIMIT( |
519 | val / 1000, | 519 | val / 1000, |
520 | (ptemp[0] & 0x7C) + 4, | 520 | (ptemp[0] & 0x7C) + 4, |
521 | 124); | 521 | 124); |
522 | ptemp[1] &= 0x7C; | 522 | ptemp[1] &= 0x7C; |
523 | ptemp[2] = SENSORS_LIMIT( | 523 | ptemp[2] = SENSORS_LIMIT( |
524 | ptemp[2], ptemp[1] + 1, | 524 | ptemp[2], ptemp[1] + 1, |
525 | 255); | 525 | 255); |
526 | break; | 526 | break; |
527 | case 2: | 527 | case 2: |
528 | ptemp[2] = SENSORS_LIMIT( | 528 | ptemp[2] = SENSORS_LIMIT( |
529 | val / 1000, | 529 | val / 1000, |
530 | ptemp[1]+1, | 530 | ptemp[1]+1, |
531 | 255); | 531 | 255); |
532 | break; | 532 | break; |
533 | default: | 533 | default: |
534 | dev_dbg(dev, "Unknown attr->index (%d).\n", ix); | 534 | dev_dbg(dev, "Unknown attr->index (%d).\n", ix); |
535 | count = -EINVAL; | 535 | count = -EINVAL; |
536 | goto EXIT; | 536 | goto EXIT; |
537 | } | 537 | } |
538 | dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; | 538 | dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; |
539 | if (set_slope_register(client, reg, dpwm, ptemp)) | 539 | if (set_slope_register(client, reg, dpwm, ptemp)) |
540 | count = -EIO; | 540 | count = -EIO; |
541 | 541 | ||
542 | EXIT: | 542 | EXIT: |
543 | mutex_unlock(&data->update_lock); | 543 | mutex_unlock(&data->update_lock); |
544 | return count; | 544 | return count; |
545 | } | 545 | } |
546 | 546 | ||
547 | 547 | ||
548 | 548 | ||
549 | static ssize_t set_pwm1_auto_point_pwm( | 549 | static ssize_t set_pwm1_auto_point_pwm( |
550 | struct device *dev, | 550 | struct device *dev, |
551 | struct device_attribute *attr, | 551 | struct device_attribute *attr, |
552 | const char *buf, | 552 | const char *buf, |
553 | size_t count) | 553 | size_t count) |
554 | { | 554 | { |
555 | struct i2c_client *client = to_i2c_client(dev); | 555 | struct i2c_client *client = to_i2c_client(dev); |
556 | struct amc6821_data *data = i2c_get_clientdata(client); | 556 | struct amc6821_data *data = i2c_get_clientdata(client); |
557 | int dpwm; | 557 | int dpwm; |
558 | long val; | 558 | long val; |
559 | int ret = kstrtol(buf, 10, &val); | 559 | int ret = kstrtol(buf, 10, &val); |
560 | if (ret) | 560 | if (ret) |
561 | return ret; | 561 | return ret; |
562 | 562 | ||
563 | mutex_lock(&data->update_lock); | 563 | mutex_lock(&data->update_lock); |
564 | data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254); | 564 | data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254); |
565 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP, | 565 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP, |
566 | data->pwm1_auto_point_pwm[1])) { | 566 | data->pwm1_auto_point_pwm[1])) { |
567 | dev_err(&client->dev, "Register write error, aborting.\n"); | 567 | dev_err(&client->dev, "Register write error, aborting.\n"); |
568 | count = -EIO; | 568 | count = -EIO; |
569 | goto EXIT; | 569 | goto EXIT; |
570 | } | 570 | } |
571 | dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; | 571 | dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; |
572 | if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm, | 572 | if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm, |
573 | data->temp1_auto_point_temp)) { | 573 | data->temp1_auto_point_temp)) { |
574 | count = -EIO; | 574 | count = -EIO; |
575 | goto EXIT; | 575 | goto EXIT; |
576 | } | 576 | } |
577 | if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm, | 577 | if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm, |
578 | data->temp2_auto_point_temp)) { | 578 | data->temp2_auto_point_temp)) { |
579 | count = -EIO; | 579 | count = -EIO; |
580 | goto EXIT; | 580 | goto EXIT; |
581 | } | 581 | } |
582 | 582 | ||
583 | EXIT: | 583 | EXIT: |
584 | data->valid = 0; | 584 | data->valid = 0; |
585 | mutex_unlock(&data->update_lock); | 585 | mutex_unlock(&data->update_lock); |
586 | return count; | 586 | return count; |
587 | } | 587 | } |
588 | 588 | ||
589 | static ssize_t get_fan( | 589 | static ssize_t get_fan( |
590 | struct device *dev, | 590 | struct device *dev, |
591 | struct device_attribute *devattr, | 591 | struct device_attribute *devattr, |
592 | char *buf) | 592 | char *buf) |
593 | { | 593 | { |
594 | struct amc6821_data *data = amc6821_update_device(dev); | 594 | struct amc6821_data *data = amc6821_update_device(dev); |
595 | int ix = to_sensor_dev_attr(devattr)->index; | 595 | int ix = to_sensor_dev_attr(devattr)->index; |
596 | if (0 == data->fan[ix]) | 596 | if (0 == data->fan[ix]) |
597 | return sprintf(buf, "0"); | 597 | return sprintf(buf, "0"); |
598 | return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix])); | 598 | return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix])); |
599 | } | 599 | } |
600 | 600 | ||
601 | 601 | ||
602 | 602 | ||
603 | static ssize_t get_fan1_fault( | 603 | static ssize_t get_fan1_fault( |
604 | struct device *dev, | 604 | struct device *dev, |
605 | struct device_attribute *devattr, | 605 | struct device_attribute *devattr, |
606 | char *buf) | 606 | char *buf) |
607 | { | 607 | { |
608 | struct amc6821_data *data = amc6821_update_device(dev); | 608 | struct amc6821_data *data = amc6821_update_device(dev); |
609 | if (data->stat1 & AMC6821_STAT1_FANS) | 609 | if (data->stat1 & AMC6821_STAT1_FANS) |
610 | return sprintf(buf, "1"); | 610 | return sprintf(buf, "1"); |
611 | else | 611 | else |
612 | return sprintf(buf, "0"); | 612 | return sprintf(buf, "0"); |
613 | } | 613 | } |
614 | 614 | ||
615 | 615 | ||
616 | 616 | ||
617 | static ssize_t set_fan( | 617 | static ssize_t set_fan( |
618 | struct device *dev, | 618 | struct device *dev, |
619 | struct device_attribute *attr, | 619 | struct device_attribute *attr, |
620 | const char *buf, size_t count) | 620 | const char *buf, size_t count) |
621 | { | 621 | { |
622 | struct i2c_client *client = to_i2c_client(dev); | 622 | struct i2c_client *client = to_i2c_client(dev); |
623 | struct amc6821_data *data = i2c_get_clientdata(client); | 623 | struct amc6821_data *data = i2c_get_clientdata(client); |
624 | long val; | 624 | long val; |
625 | int ix = to_sensor_dev_attr(attr)->index; | 625 | int ix = to_sensor_dev_attr(attr)->index; |
626 | int ret = kstrtol(buf, 10, &val); | 626 | int ret = kstrtol(buf, 10, &val); |
627 | if (ret) | 627 | if (ret) |
628 | return ret; | 628 | return ret; |
629 | val = 1 > val ? 0xFFFF : 6000000/val; | 629 | val = 1 > val ? 0xFFFF : 6000000/val; |
630 | 630 | ||
631 | mutex_lock(&data->update_lock); | 631 | mutex_lock(&data->update_lock); |
632 | data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF); | 632 | data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF); |
633 | if (i2c_smbus_write_byte_data(client, fan_reg_low[ix], | 633 | if (i2c_smbus_write_byte_data(client, fan_reg_low[ix], |
634 | data->fan[ix] & 0xFF)) { | 634 | data->fan[ix] & 0xFF)) { |
635 | dev_err(&client->dev, "Register write error, aborting.\n"); | 635 | dev_err(&client->dev, "Register write error, aborting.\n"); |
636 | count = -EIO; | 636 | count = -EIO; |
637 | goto EXIT; | 637 | goto EXIT; |
638 | } | 638 | } |
639 | if (i2c_smbus_write_byte_data(client, | 639 | if (i2c_smbus_write_byte_data(client, |
640 | fan_reg_hi[ix], data->fan[ix] >> 8)) { | 640 | fan_reg_hi[ix], data->fan[ix] >> 8)) { |
641 | dev_err(&client->dev, "Register write error, aborting.\n"); | 641 | dev_err(&client->dev, "Register write error, aborting.\n"); |
642 | count = -EIO; | 642 | count = -EIO; |
643 | } | 643 | } |
644 | EXIT: | 644 | EXIT: |
645 | mutex_unlock(&data->update_lock); | 645 | mutex_unlock(&data->update_lock); |
646 | return count; | 646 | return count; |
647 | } | 647 | } |
648 | 648 | ||
649 | 649 | ||
650 | 650 | ||
651 | static ssize_t get_fan1_div( | 651 | static ssize_t get_fan1_div( |
652 | struct device *dev, | 652 | struct device *dev, |
653 | struct device_attribute *devattr, | 653 | struct device_attribute *devattr, |
654 | char *buf) | 654 | char *buf) |
655 | { | 655 | { |
656 | struct amc6821_data *data = amc6821_update_device(dev); | 656 | struct amc6821_data *data = amc6821_update_device(dev); |
657 | return sprintf(buf, "%d\n", data->fan1_div); | 657 | return sprintf(buf, "%d\n", data->fan1_div); |
658 | } | 658 | } |
659 | 659 | ||
660 | static ssize_t set_fan1_div( | 660 | static ssize_t set_fan1_div( |
661 | struct device *dev, | 661 | struct device *dev, |
662 | struct device_attribute *attr, | 662 | struct device_attribute *attr, |
663 | const char *buf, size_t count) | 663 | const char *buf, size_t count) |
664 | { | 664 | { |
665 | struct i2c_client *client = to_i2c_client(dev); | 665 | struct i2c_client *client = to_i2c_client(dev); |
666 | struct amc6821_data *data = i2c_get_clientdata(client); | 666 | struct amc6821_data *data = i2c_get_clientdata(client); |
667 | long val; | 667 | long val; |
668 | int config = kstrtol(buf, 10, &val); | 668 | int config = kstrtol(buf, 10, &val); |
669 | if (config) | 669 | if (config) |
670 | return config; | 670 | return config; |
671 | 671 | ||
672 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); | 672 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); |
673 | if (config < 0) { | 673 | if (config < 0) { |
674 | dev_err(&client->dev, | 674 | dev_err(&client->dev, |
675 | "Error reading configuration register, aborting.\n"); | 675 | "Error reading configuration register, aborting.\n"); |
676 | return -EIO; | 676 | return -EIO; |
677 | } | 677 | } |
678 | mutex_lock(&data->update_lock); | 678 | mutex_lock(&data->update_lock); |
679 | switch (val) { | 679 | switch (val) { |
680 | case 2: | 680 | case 2: |
681 | config &= ~AMC6821_CONF4_PSPR; | 681 | config &= ~AMC6821_CONF4_PSPR; |
682 | data->fan1_div = 2; | 682 | data->fan1_div = 2; |
683 | break; | 683 | break; |
684 | case 4: | 684 | case 4: |
685 | config |= AMC6821_CONF4_PSPR; | 685 | config |= AMC6821_CONF4_PSPR; |
686 | data->fan1_div = 4; | 686 | data->fan1_div = 4; |
687 | break; | 687 | break; |
688 | default: | 688 | default: |
689 | count = -EINVAL; | 689 | count = -EINVAL; |
690 | goto EXIT; | 690 | goto EXIT; |
691 | } | 691 | } |
692 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) { | 692 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) { |
693 | dev_err(&client->dev, | 693 | dev_err(&client->dev, |
694 | "Configuration register write error, aborting.\n"); | 694 | "Configuration register write error, aborting.\n"); |
695 | count = -EIO; | 695 | count = -EIO; |
696 | } | 696 | } |
697 | EXIT: | 697 | EXIT: |
698 | mutex_unlock(&data->update_lock); | 698 | mutex_unlock(&data->update_lock); |
699 | return count; | 699 | return count; |
700 | } | 700 | } |
701 | 701 | ||
702 | 702 | ||
703 | 703 | ||
704 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, | 704 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, |
705 | get_temp, NULL, IDX_TEMP1_INPUT); | 705 | get_temp, NULL, IDX_TEMP1_INPUT); |
706 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp, | 706 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp, |
707 | set_temp, IDX_TEMP1_MIN); | 707 | set_temp, IDX_TEMP1_MIN); |
708 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp, | 708 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp, |
709 | set_temp, IDX_TEMP1_MAX); | 709 | set_temp, IDX_TEMP1_MAX); |
710 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp, | 710 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp, |
711 | set_temp, IDX_TEMP1_CRIT); | 711 | set_temp, IDX_TEMP1_CRIT); |
712 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, | 712 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, |
713 | get_temp_alarm, NULL, IDX_TEMP1_MIN); | 713 | get_temp_alarm, NULL, IDX_TEMP1_MIN); |
714 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, | 714 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, |
715 | get_temp_alarm, NULL, IDX_TEMP1_MAX); | 715 | get_temp_alarm, NULL, IDX_TEMP1_MAX); |
716 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, | 716 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, |
717 | get_temp_alarm, NULL, IDX_TEMP1_CRIT); | 717 | get_temp_alarm, NULL, IDX_TEMP1_CRIT); |
718 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO | S_IWUSR, | 718 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO | S_IWUSR, |
719 | get_temp, NULL, IDX_TEMP2_INPUT); | 719 | get_temp, NULL, IDX_TEMP2_INPUT); |
720 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp, | 720 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp, |
721 | set_temp, IDX_TEMP2_MIN); | 721 | set_temp, IDX_TEMP2_MIN); |
722 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp, | 722 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp, |
723 | set_temp, IDX_TEMP2_MAX); | 723 | set_temp, IDX_TEMP2_MAX); |
724 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp, | 724 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp, |
725 | set_temp, IDX_TEMP2_CRIT); | 725 | set_temp, IDX_TEMP2_CRIT); |
726 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, | 726 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, |
727 | get_temp2_fault, NULL, 0); | 727 | get_temp2_fault, NULL, 0); |
728 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, | 728 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, |
729 | get_temp_alarm, NULL, IDX_TEMP2_MIN); | 729 | get_temp_alarm, NULL, IDX_TEMP2_MIN); |
730 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, | 730 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, |
731 | get_temp_alarm, NULL, IDX_TEMP2_MAX); | 731 | get_temp_alarm, NULL, IDX_TEMP2_MAX); |
732 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, | 732 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, |
733 | get_temp_alarm, NULL, IDX_TEMP2_CRIT); | 733 | get_temp_alarm, NULL, IDX_TEMP2_CRIT); |
734 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT); | 734 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT); |
735 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, | 735 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, |
736 | get_fan, set_fan, IDX_FAN1_MIN); | 736 | get_fan, set_fan, IDX_FAN1_MIN); |
737 | static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR, | 737 | static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR, |
738 | get_fan, set_fan, IDX_FAN1_MAX); | 738 | get_fan, set_fan, IDX_FAN1_MAX); |
739 | static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0); | 739 | static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0); |
740 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, | 740 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, |
741 | get_fan1_div, set_fan1_div, 0); | 741 | get_fan1_div, set_fan1_div, 0); |
742 | 742 | ||
743 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0); | 743 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0); |
744 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | 744 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, |
745 | get_pwm1_enable, set_pwm1_enable, 0); | 745 | get_pwm1_enable, set_pwm1_enable, 0); |
746 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, | 746 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, |
747 | get_pwm1_auto_point_pwm, NULL, 0); | 747 | get_pwm1_auto_point_pwm, NULL, 0); |
748 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, | 748 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, |
749 | get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1); | 749 | get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1); |
750 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, | 750 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, |
751 | get_pwm1_auto_point_pwm, NULL, 2); | 751 | get_pwm1_auto_point_pwm, NULL, 2); |
752 | static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO, | 752 | static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO, |
753 | get_pwm1_auto_channels_temp, NULL, 0); | 753 | get_pwm1_auto_channels_temp, NULL, 0); |
754 | static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO, | 754 | static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO, |
755 | get_temp_auto_point_temp, NULL, 1, 0); | 755 | get_temp_auto_point_temp, NULL, 1, 0); |
756 | static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, | 756 | static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, |
757 | get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1); | 757 | get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1); |
758 | static SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO, | 758 | static SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO, |
759 | get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2); | 759 | get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2); |
760 | 760 | ||
761 | static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, | 761 | static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, |
762 | get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0); | 762 | get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0); |
763 | static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, | 763 | static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, |
764 | get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1); | 764 | get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1); |
765 | static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO, | 765 | static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO, |
766 | get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2); | 766 | get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2); |
767 | 767 | ||
768 | 768 | ||
769 | 769 | ||
770 | static struct attribute *amc6821_attrs[] = { | 770 | static struct attribute *amc6821_attrs[] = { |
771 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 771 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
772 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 772 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
773 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 773 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
774 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | 774 | &sensor_dev_attr_temp1_crit.dev_attr.attr, |
775 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | 775 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, |
776 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | 776 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, |
777 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | 777 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, |
778 | &sensor_dev_attr_temp2_input.dev_attr.attr, | 778 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
779 | &sensor_dev_attr_temp2_min.dev_attr.attr, | 779 | &sensor_dev_attr_temp2_min.dev_attr.attr, |
780 | &sensor_dev_attr_temp2_max.dev_attr.attr, | 780 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
781 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | 781 | &sensor_dev_attr_temp2_crit.dev_attr.attr, |
782 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | 782 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, |
783 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | 783 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, |
784 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | 784 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, |
785 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | 785 | &sensor_dev_attr_temp2_fault.dev_attr.attr, |
786 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 786 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
787 | &sensor_dev_attr_fan1_min.dev_attr.attr, | 787 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
788 | &sensor_dev_attr_fan1_max.dev_attr.attr, | 788 | &sensor_dev_attr_fan1_max.dev_attr.attr, |
789 | &sensor_dev_attr_fan1_fault.dev_attr.attr, | 789 | &sensor_dev_attr_fan1_fault.dev_attr.attr, |
790 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 790 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
791 | &sensor_dev_attr_pwm1.dev_attr.attr, | 791 | &sensor_dev_attr_pwm1.dev_attr.attr, |
792 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | 792 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
793 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | 793 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, |
794 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | 794 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, |
795 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | 795 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, |
796 | &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, | 796 | &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, |
797 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | 797 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, |
798 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, | 798 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, |
799 | &sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr, | 799 | &sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr, |
800 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, | 800 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, |
801 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, | 801 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, |
802 | &sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr, | 802 | &sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr, |
803 | NULL | 803 | NULL |
804 | }; | 804 | }; |
805 | 805 | ||
806 | static struct attribute_group amc6821_attr_grp = { | 806 | static struct attribute_group amc6821_attr_grp = { |
807 | .attrs = amc6821_attrs, | 807 | .attrs = amc6821_attrs, |
808 | }; | 808 | }; |
809 | 809 | ||
810 | 810 | ||
811 | 811 | ||
812 | /* Return 0 if detection is successful, -ENODEV otherwise */ | 812 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
813 | static int amc6821_detect( | 813 | static int amc6821_detect( |
814 | struct i2c_client *client, | 814 | struct i2c_client *client, |
815 | struct i2c_board_info *info) | 815 | struct i2c_board_info *info) |
816 | { | 816 | { |
817 | struct i2c_adapter *adapter = client->adapter; | 817 | struct i2c_adapter *adapter = client->adapter; |
818 | int address = client->addr; | 818 | int address = client->addr; |
819 | int dev_id, comp_id; | 819 | int dev_id, comp_id; |
820 | 820 | ||
821 | dev_dbg(&adapter->dev, "amc6821_detect called.\n"); | 821 | dev_dbg(&adapter->dev, "amc6821_detect called.\n"); |
822 | 822 | ||
823 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 823 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
824 | dev_dbg(&adapter->dev, | 824 | dev_dbg(&adapter->dev, |
825 | "amc6821: I2C bus doesn't support byte mode, " | 825 | "amc6821: I2C bus doesn't support byte mode, " |
826 | "skipping.\n"); | 826 | "skipping.\n"); |
827 | return -ENODEV; | 827 | return -ENODEV; |
828 | } | 828 | } |
829 | 829 | ||
830 | dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID); | 830 | dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID); |
831 | comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID); | 831 | comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID); |
832 | if (dev_id != 0x21 || comp_id != 0x49) { | 832 | if (dev_id != 0x21 || comp_id != 0x49) { |
833 | dev_dbg(&adapter->dev, | 833 | dev_dbg(&adapter->dev, |
834 | "amc6821: detection failed at 0x%02x.\n", | 834 | "amc6821: detection failed at 0x%02x.\n", |
835 | address); | 835 | address); |
836 | return -ENODEV; | 836 | return -ENODEV; |
837 | } | 837 | } |
838 | 838 | ||
839 | /* | 839 | /* |
840 | * Bit 7 of the address register is ignored, so we can check the | 840 | * Bit 7 of the address register is ignored, so we can check the |
841 | * ID registers again | 841 | * ID registers again |
842 | */ | 842 | */ |
843 | dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID); | 843 | dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID); |
844 | comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID); | 844 | comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID); |
845 | if (dev_id != 0x21 || comp_id != 0x49) { | 845 | if (dev_id != 0x21 || comp_id != 0x49) { |
846 | dev_dbg(&adapter->dev, | 846 | dev_dbg(&adapter->dev, |
847 | "amc6821: detection failed at 0x%02x.\n", | 847 | "amc6821: detection failed at 0x%02x.\n", |
848 | address); | 848 | address); |
849 | return -ENODEV; | 849 | return -ENODEV; |
850 | } | 850 | } |
851 | 851 | ||
852 | dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address); | 852 | dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address); |
853 | strlcpy(info->type, "amc6821", I2C_NAME_SIZE); | 853 | strlcpy(info->type, "amc6821", I2C_NAME_SIZE); |
854 | 854 | ||
855 | return 0; | 855 | return 0; |
856 | } | 856 | } |
857 | 857 | ||
858 | static int amc6821_probe( | 858 | static int amc6821_probe( |
859 | struct i2c_client *client, | 859 | struct i2c_client *client, |
860 | const struct i2c_device_id *id) | 860 | const struct i2c_device_id *id) |
861 | { | 861 | { |
862 | struct amc6821_data *data; | 862 | struct amc6821_data *data; |
863 | int err; | 863 | int err; |
864 | 864 | ||
865 | data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL); | 865 | data = devm_kzalloc(&client->dev, sizeof(struct amc6821_data), |
866 | if (!data) { | 866 | GFP_KERNEL); |
867 | dev_err(&client->dev, "out of memory.\n"); | 867 | if (!data) |
868 | return -ENOMEM; | 868 | return -ENOMEM; |
869 | } | ||
870 | 869 | ||
871 | |||
872 | i2c_set_clientdata(client, data); | 870 | i2c_set_clientdata(client, data); |
873 | mutex_init(&data->update_lock); | 871 | mutex_init(&data->update_lock); |
874 | 872 | ||
875 | /* | 873 | /* |
876 | * Initialize the amc6821 chip | 874 | * Initialize the amc6821 chip |
877 | */ | 875 | */ |
878 | err = amc6821_init_client(client); | 876 | err = amc6821_init_client(client); |
879 | if (err) | 877 | if (err) |
880 | goto err_free; | 878 | return err; |
881 | 879 | ||
882 | err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); | 880 | err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); |
883 | if (err) | 881 | if (err) |
884 | goto err_free; | 882 | return err; |
885 | 883 | ||
886 | data->hwmon_dev = hwmon_device_register(&client->dev); | 884 | data->hwmon_dev = hwmon_device_register(&client->dev); |
887 | if (!IS_ERR(data->hwmon_dev)) | 885 | if (!IS_ERR(data->hwmon_dev)) |
888 | return 0; | 886 | return 0; |
889 | 887 | ||
890 | err = PTR_ERR(data->hwmon_dev); | 888 | err = PTR_ERR(data->hwmon_dev); |
891 | dev_err(&client->dev, "error registering hwmon device.\n"); | 889 | dev_err(&client->dev, "error registering hwmon device.\n"); |
892 | sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); | 890 | sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); |
893 | err_free: | ||
894 | kfree(data); | ||
895 | return err; | 891 | return err; |
896 | } | 892 | } |
897 | 893 | ||
898 | static int amc6821_remove(struct i2c_client *client) | 894 | static int amc6821_remove(struct i2c_client *client) |
899 | { | 895 | { |
900 | struct amc6821_data *data = i2c_get_clientdata(client); | 896 | struct amc6821_data *data = i2c_get_clientdata(client); |
901 | 897 | ||
902 | hwmon_device_unregister(data->hwmon_dev); | 898 | hwmon_device_unregister(data->hwmon_dev); |
903 | sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); | 899 | sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); |
904 | |||
905 | kfree(data); | ||
906 | 900 | ||
907 | return 0; | 901 | return 0; |
908 | } | 902 | } |
909 | 903 | ||
910 | 904 | ||
911 | static int amc6821_init_client(struct i2c_client *client) | 905 | static int amc6821_init_client(struct i2c_client *client) |
912 | { | 906 | { |
913 | int config; | 907 | int config; |
914 | int err = -EIO; | 908 | int err = -EIO; |
915 | 909 | ||
916 | if (init) { | 910 | if (init) { |
917 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); | 911 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); |
918 | 912 | ||
919 | if (config < 0) { | 913 | if (config < 0) { |
920 | dev_err(&client->dev, | 914 | dev_err(&client->dev, |
921 | "Error reading configuration register, aborting.\n"); | 915 | "Error reading configuration register, aborting.\n"); |
922 | return err; | 916 | return err; |
923 | } | 917 | } |
924 | 918 | ||
925 | config |= AMC6821_CONF4_MODE; | 919 | config |= AMC6821_CONF4_MODE; |
926 | 920 | ||
927 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, | 921 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, |
928 | config)) { | 922 | config)) { |
929 | dev_err(&client->dev, | 923 | dev_err(&client->dev, |
930 | "Configuration register write error, aborting.\n"); | 924 | "Configuration register write error, aborting.\n"); |
931 | return err; | 925 | return err; |
932 | } | 926 | } |
933 | 927 | ||
934 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3); | 928 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3); |
935 | 929 | ||
936 | if (config < 0) { | 930 | if (config < 0) { |
937 | dev_err(&client->dev, | 931 | dev_err(&client->dev, |
938 | "Error reading configuration register, aborting.\n"); | 932 | "Error reading configuration register, aborting.\n"); |
939 | return err; | 933 | return err; |
940 | } | 934 | } |
941 | 935 | ||
942 | dev_info(&client->dev, "Revision %d\n", config & 0x0f); | 936 | dev_info(&client->dev, "Revision %d\n", config & 0x0f); |
943 | 937 | ||
944 | config &= ~AMC6821_CONF3_THERM_FAN_EN; | 938 | config &= ~AMC6821_CONF3_THERM_FAN_EN; |
945 | 939 | ||
946 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3, | 940 | if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3, |
947 | config)) { | 941 | config)) { |
948 | dev_err(&client->dev, | 942 | dev_err(&client->dev, |
949 | "Configuration register write error, aborting.\n"); | 943 | "Configuration register write error, aborting.\n"); |
950 | return err; | 944 | return err; |
951 | } | 945 | } |
952 | 946 | ||
953 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2); | 947 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2); |
954 | 948 | ||
955 | if (config < 0) { | 949 | if (config < 0) { |
956 | dev_err(&client->dev, | 950 | dev_err(&client->dev, |
957 | "Error reading configuration register, aborting.\n"); | 951 | "Error reading configuration register, aborting.\n"); |
958 | return err; | 952 | return err; |
959 | } | 953 | } |
960 | 954 | ||
961 | config &= ~AMC6821_CONF2_RTFIE; | 955 | config &= ~AMC6821_CONF2_RTFIE; |
962 | config &= ~AMC6821_CONF2_LTOIE; | 956 | config &= ~AMC6821_CONF2_LTOIE; |
963 | config &= ~AMC6821_CONF2_RTOIE; | 957 | config &= ~AMC6821_CONF2_RTOIE; |
964 | if (i2c_smbus_write_byte_data(client, | 958 | if (i2c_smbus_write_byte_data(client, |
965 | AMC6821_REG_CONF2, config)) { | 959 | AMC6821_REG_CONF2, config)) { |
966 | dev_err(&client->dev, | 960 | dev_err(&client->dev, |
967 | "Configuration register write error, aborting.\n"); | 961 | "Configuration register write error, aborting.\n"); |
968 | return err; | 962 | return err; |
969 | } | 963 | } |
970 | 964 | ||
971 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); | 965 | config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); |
972 | 966 | ||
973 | if (config < 0) { | 967 | if (config < 0) { |
974 | dev_err(&client->dev, | 968 | dev_err(&client->dev, |
975 | "Error reading configuration register, aborting.\n"); | 969 | "Error reading configuration register, aborting.\n"); |
976 | return err; | 970 | return err; |
977 | } | 971 | } |
978 | 972 | ||
979 | config &= ~AMC6821_CONF1_THERMOVIE; | 973 | config &= ~AMC6821_CONF1_THERMOVIE; |
980 | config &= ~AMC6821_CONF1_FANIE; | 974 | config &= ~AMC6821_CONF1_FANIE; |
981 | config |= AMC6821_CONF1_START; | 975 | config |= AMC6821_CONF1_START; |
982 | if (pwminv) | 976 | if (pwminv) |
983 | config |= AMC6821_CONF1_PWMINV; | 977 | config |= AMC6821_CONF1_PWMINV; |
984 | else | 978 | else |
985 | config &= ~AMC6821_CONF1_PWMINV; | 979 | config &= ~AMC6821_CONF1_PWMINV; |
986 | 980 | ||
987 | if (i2c_smbus_write_byte_data( | 981 | if (i2c_smbus_write_byte_data( |
988 | client, AMC6821_REG_CONF1, config)) { | 982 | client, AMC6821_REG_CONF1, config)) { |
989 | dev_err(&client->dev, | 983 | dev_err(&client->dev, |
990 | "Configuration register write error, aborting.\n"); | 984 | "Configuration register write error, aborting.\n"); |
991 | return err; | 985 | return err; |
992 | } | 986 | } |
993 | } | 987 | } |
994 | return 0; | 988 | return 0; |
995 | } | 989 | } |
996 | 990 | ||
997 | 991 | ||
998 | static struct amc6821_data *amc6821_update_device(struct device *dev) | 992 | static struct amc6821_data *amc6821_update_device(struct device *dev) |
999 | { | 993 | { |
1000 | struct i2c_client *client = to_i2c_client(dev); | 994 | struct i2c_client *client = to_i2c_client(dev); |
1001 | struct amc6821_data *data = i2c_get_clientdata(client); | 995 | struct amc6821_data *data = i2c_get_clientdata(client); |
1002 | int timeout = HZ; | 996 | int timeout = HZ; |
1003 | u8 reg; | 997 | u8 reg; |
1004 | int i; | 998 | int i; |
1005 | 999 | ||
1006 | mutex_lock(&data->update_lock); | 1000 | mutex_lock(&data->update_lock); |
1007 | 1001 | ||
1008 | if (time_after(jiffies, data->last_updated + timeout) || | 1002 | if (time_after(jiffies, data->last_updated + timeout) || |
1009 | !data->valid) { | 1003 | !data->valid) { |
1010 | 1004 | ||
1011 | for (i = 0; i < TEMP_IDX_LEN; i++) | 1005 | for (i = 0; i < TEMP_IDX_LEN; i++) |
1012 | data->temp[i] = i2c_smbus_read_byte_data(client, | 1006 | data->temp[i] = i2c_smbus_read_byte_data(client, |
1013 | temp_reg[i]); | 1007 | temp_reg[i]); |
1014 | 1008 | ||
1015 | data->stat1 = i2c_smbus_read_byte_data(client, | 1009 | data->stat1 = i2c_smbus_read_byte_data(client, |
1016 | AMC6821_REG_STAT1); | 1010 | AMC6821_REG_STAT1); |
1017 | data->stat2 = i2c_smbus_read_byte_data(client, | 1011 | data->stat2 = i2c_smbus_read_byte_data(client, |
1018 | AMC6821_REG_STAT2); | 1012 | AMC6821_REG_STAT2); |
1019 | 1013 | ||
1020 | data->pwm1 = i2c_smbus_read_byte_data(client, | 1014 | data->pwm1 = i2c_smbus_read_byte_data(client, |
1021 | AMC6821_REG_DCY); | 1015 | AMC6821_REG_DCY); |
1022 | for (i = 0; i < FAN1_IDX_LEN; i++) { | 1016 | for (i = 0; i < FAN1_IDX_LEN; i++) { |
1023 | data->fan[i] = i2c_smbus_read_byte_data( | 1017 | data->fan[i] = i2c_smbus_read_byte_data( |
1024 | client, | 1018 | client, |
1025 | fan_reg_low[i]); | 1019 | fan_reg_low[i]); |
1026 | data->fan[i] += i2c_smbus_read_byte_data( | 1020 | data->fan[i] += i2c_smbus_read_byte_data( |
1027 | client, | 1021 | client, |
1028 | fan_reg_hi[i]) << 8; | 1022 | fan_reg_hi[i]) << 8; |
1029 | } | 1023 | } |
1030 | data->fan1_div = i2c_smbus_read_byte_data(client, | 1024 | data->fan1_div = i2c_smbus_read_byte_data(client, |
1031 | AMC6821_REG_CONF4); | 1025 | AMC6821_REG_CONF4); |
1032 | data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; | 1026 | data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; |
1033 | 1027 | ||
1034 | data->pwm1_auto_point_pwm[0] = 0; | 1028 | data->pwm1_auto_point_pwm[0] = 0; |
1035 | data->pwm1_auto_point_pwm[2] = 255; | 1029 | data->pwm1_auto_point_pwm[2] = 255; |
1036 | data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, | 1030 | data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, |
1037 | AMC6821_REG_DCY_LOW_TEMP); | 1031 | AMC6821_REG_DCY_LOW_TEMP); |
1038 | 1032 | ||
1039 | data->temp1_auto_point_temp[0] = | 1033 | data->temp1_auto_point_temp[0] = |
1040 | i2c_smbus_read_byte_data(client, | 1034 | i2c_smbus_read_byte_data(client, |
1041 | AMC6821_REG_PSV_TEMP); | 1035 | AMC6821_REG_PSV_TEMP); |
1042 | data->temp2_auto_point_temp[0] = | 1036 | data->temp2_auto_point_temp[0] = |
1043 | data->temp1_auto_point_temp[0]; | 1037 | data->temp1_auto_point_temp[0]; |
1044 | reg = i2c_smbus_read_byte_data(client, | 1038 | reg = i2c_smbus_read_byte_data(client, |
1045 | AMC6821_REG_LTEMP_FAN_CTRL); | 1039 | AMC6821_REG_LTEMP_FAN_CTRL); |
1046 | data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; | 1040 | data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; |
1047 | reg &= 0x07; | 1041 | reg &= 0x07; |
1048 | reg = 0x20 >> reg; | 1042 | reg = 0x20 >> reg; |
1049 | if (reg > 0) | 1043 | if (reg > 0) |
1050 | data->temp1_auto_point_temp[2] = | 1044 | data->temp1_auto_point_temp[2] = |
1051 | data->temp1_auto_point_temp[1] + | 1045 | data->temp1_auto_point_temp[1] + |
1052 | (data->pwm1_auto_point_pwm[2] - | 1046 | (data->pwm1_auto_point_pwm[2] - |
1053 | data->pwm1_auto_point_pwm[1]) / reg; | 1047 | data->pwm1_auto_point_pwm[1]) / reg; |
1054 | else | 1048 | else |
1055 | data->temp1_auto_point_temp[2] = 255; | 1049 | data->temp1_auto_point_temp[2] = 255; |
1056 | 1050 | ||
1057 | reg = i2c_smbus_read_byte_data(client, | 1051 | reg = i2c_smbus_read_byte_data(client, |
1058 | AMC6821_REG_RTEMP_FAN_CTRL); | 1052 | AMC6821_REG_RTEMP_FAN_CTRL); |
1059 | data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; | 1053 | data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; |
1060 | reg &= 0x07; | 1054 | reg &= 0x07; |
1061 | reg = 0x20 >> reg; | 1055 | reg = 0x20 >> reg; |
1062 | if (reg > 0) | 1056 | if (reg > 0) |
1063 | data->temp2_auto_point_temp[2] = | 1057 | data->temp2_auto_point_temp[2] = |
1064 | data->temp2_auto_point_temp[1] + | 1058 | data->temp2_auto_point_temp[1] + |
1065 | (data->pwm1_auto_point_pwm[2] - | 1059 | (data->pwm1_auto_point_pwm[2] - |
1066 | data->pwm1_auto_point_pwm[1]) / reg; | 1060 | data->pwm1_auto_point_pwm[1]) / reg; |
1067 | else | 1061 | else |
1068 | data->temp2_auto_point_temp[2] = 255; | 1062 | data->temp2_auto_point_temp[2] = 255; |
1069 | 1063 | ||
1070 | reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); | 1064 | reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); |
1071 | reg = (reg >> 5) & 0x3; | 1065 | reg = (reg >> 5) & 0x3; |
1072 | switch (reg) { | 1066 | switch (reg) { |
1073 | case 0: /*open loop: software sets pwm1*/ | 1067 | case 0: /*open loop: software sets pwm1*/ |
1074 | data->pwm1_auto_channels_temp = 0; | 1068 | data->pwm1_auto_channels_temp = 0; |
1075 | data->pwm1_enable = 1; | 1069 | data->pwm1_enable = 1; |
1076 | break; | 1070 | break; |
1077 | case 2: /*closed loop: remote T (temp2)*/ | 1071 | case 2: /*closed loop: remote T (temp2)*/ |
1078 | data->pwm1_auto_channels_temp = 2; | 1072 | data->pwm1_auto_channels_temp = 2; |
1079 | data->pwm1_enable = 2; | 1073 | data->pwm1_enable = 2; |
1080 | break; | 1074 | break; |
1081 | case 3: /*closed loop: local and remote T (temp2)*/ | 1075 | case 3: /*closed loop: local and remote T (temp2)*/ |
1082 | data->pwm1_auto_channels_temp = 3; | 1076 | data->pwm1_auto_channels_temp = 3; |
1083 | data->pwm1_enable = 3; | 1077 | data->pwm1_enable = 3; |
1084 | break; | 1078 | break; |
1085 | case 1: /* | 1079 | case 1: /* |
1086 | * semi-open loop: software sets rpm, chip controls | 1080 | * semi-open loop: software sets rpm, chip controls |
1087 | * pwm1, currently not implemented | 1081 | * pwm1, currently not implemented |
1088 | */ | 1082 | */ |
1089 | data->pwm1_auto_channels_temp = 0; | 1083 | data->pwm1_auto_channels_temp = 0; |
1090 | data->pwm1_enable = 0; | 1084 | data->pwm1_enable = 0; |
1091 | break; | 1085 | break; |
1092 | } | 1086 | } |
1093 | 1087 | ||
1094 | data->last_updated = jiffies; | 1088 | data->last_updated = jiffies; |
1095 | data->valid = 1; | 1089 | data->valid = 1; |
1096 | } | 1090 | } |
1097 | mutex_unlock(&data->update_lock); | 1091 | mutex_unlock(&data->update_lock); |
1098 | return data; | 1092 | return data; |
1099 | } | 1093 | } |
1100 | 1094 | ||
1101 | module_i2c_driver(amc6821_driver); | 1095 | module_i2c_driver(amc6821_driver); |
1102 | 1096 | ||
1103 | MODULE_LICENSE("GPL"); | 1097 | MODULE_LICENSE("GPL"); |
1104 | MODULE_AUTHOR("T. Mertelj <tomaz.mertelj@guest.arnes.si>"); | 1098 | MODULE_AUTHOR("T. Mertelj <tomaz.mertelj@guest.arnes.si>"); |
1105 | MODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver"); | 1099 | MODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver"); |
1106 | 1100 |