Blame view

drivers/hwmon/adm1026.c 58.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
      adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
  	     monitoring
      Copyright (C) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
      Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
  
      Chip details at:
631dd1a88   Justin P. Mattock   Update broken web...
8
      <http://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/i2c.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
29
  #include <linux/hwmon.h>
303760b44   Jean Delvare   [PATCH] hwmon: hw...
30
31
  #include <linux/hwmon-sysfs.h>
  #include <linux/hwmon-vid.h>
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
32
  #include <linux/err.h>
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
33
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  
  /* Addresses to scan */
25e9c86d5   Mark M. Hoffman   hwmon: normal_i2c...
36
  static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

cb01a2312   Jean Delvare   hwmon: (adm1026) ...
38
39
  static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
  				-1, -1, -1, -1, -1, -1, -1, -1 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
  static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
  				-1, -1, -1, -1, -1, -1, -1, -1 };
  static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
  				-1, -1, -1, -1, -1, -1, -1, -1 };
  static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
  				-1, -1, -1, -1, -1, -1, -1, -1 };
  static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
47
48
49
50
  module_param_array(gpio_input, int, NULL, 0);
  MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
  module_param_array(gpio_output, int, NULL, 0);
  MODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  	"outputs");
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
52
53
  module_param_array(gpio_inverted, int, NULL, 0);
  MODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  	"inverted");
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
55
56
  module_param_array(gpio_normal, int, NULL, 0);
  MODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  	"normal/non-inverted");
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
58
59
  module_param_array(gpio_fan, int, NULL, 0);
  MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
  
  /* Many ADM1026 constants specified below */
  
  /* The ADM1026 registers */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
64
65
66
67
68
69
70
71
72
73
74
  #define ADM1026_REG_CONFIG1	0x00
  #define CFG1_MONITOR		0x01
  #define CFG1_INT_ENABLE		0x02
  #define CFG1_INT_CLEAR		0x04
  #define CFG1_AIN8_9		0x08
  #define CFG1_THERM_HOT		0x10
  #define CFG1_DAC_AFC		0x20
  #define CFG1_PWM_AFC		0x40
  #define CFG1_RESET		0x80
  
  #define ADM1026_REG_CONFIG2	0x01
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  /* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  
  #define ADM1026_REG_CONFIG3	0x07
  #define CFG3_GPIO16_ENABLE	0x01
  #define CFG3_CI_CLEAR		0x02
  #define CFG3_VREF_250		0x04
  #define CFG3_GPIO16_DIR		0x40
  #define CFG3_GPIO16_POL		0x80
  
  #define ADM1026_REG_E2CONFIG	0x13
  #define E2CFG_READ		0x01
  #define E2CFG_WRITE		0x02
  #define E2CFG_ERASE		0x04
  #define E2CFG_ROM		0x08
  #define E2CFG_CLK_EXT		0x80
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  
  /* There are 10 general analog inputs and 7 dedicated inputs
   * They are:
   *    0 - 9  =  AIN0 - AIN9
   *       10  =  Vbat
   *       11  =  3.3V Standby
   *       12  =  3.3V Main
   *       13  =  +5V
   *       14  =  Vccp (CPU core voltage)
   *       15  =  +12V
   *       16  =  -12V
   */
  static u16 ADM1026_REG_IN[] = {
  		0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
  		0x36, 0x37, 0x27, 0x29, 0x26, 0x2a,
  		0x2b, 0x2c, 0x2d, 0x2e, 0x2f
  	};
  static u16 ADM1026_REG_IN_MIN[] = {
  		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
  		0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a,
  		0x4b, 0x4c, 0x4d, 0x4e, 0x4f
  	};
  static u16 ADM1026_REG_IN_MAX[] = {
  		0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
  		0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42,
  		0x43, 0x44, 0x45, 0x46, 0x47
  	};
  
  /* Temperatures are:
   *    0 - Internal
   *    1 - External 1
   *    2 - External 2
   */
  static u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 };
  static u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 };
  static u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 };
  static u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 };
  static u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f };
  static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
129
130
131
132
  #define ADM1026_REG_FAN(nr)		(0x38 + (nr))
  #define ADM1026_REG_FAN_MIN(nr)		(0x60 + (nr))
  #define ADM1026_REG_FAN_DIV_0_3		0x02
  #define ADM1026_REG_FAN_DIV_4_7		0x03
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133

cb01a2312   Jean Delvare   hwmon: (adm1026) ...
134
135
  #define ADM1026_REG_DAC			0x04
  #define ADM1026_REG_PWM			0x05
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

cb01a2312   Jean Delvare   hwmon: (adm1026) ...
137
138
139
140
  #define ADM1026_REG_GPIO_CFG_0_3	0x08
  #define ADM1026_REG_GPIO_CFG_4_7	0x09
  #define ADM1026_REG_GPIO_CFG_8_11	0x0a
  #define ADM1026_REG_GPIO_CFG_12_15	0x0b
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  /* CFG_16 in REG_CFG3 */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
142
143
  #define ADM1026_REG_GPIO_STATUS_0_7	0x24
  #define ADM1026_REG_GPIO_STATUS_8_15	0x25
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  /* STATUS_16 in REG_STATUS4 */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
145
146
  #define ADM1026_REG_GPIO_MASK_0_7	0x1c
  #define ADM1026_REG_GPIO_MASK_8_15	0x1d
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  /* MASK_16 in REG_MASK4 */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
148
149
  #define ADM1026_REG_COMPANY		0x16
  #define ADM1026_REG_VERSTEP		0x17
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  /* These are the recognized values for the above regs */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
151
152
153
  #define ADM1026_COMPANY_ANALOG_DEV	0x41
  #define ADM1026_VERSTEP_GENERIC		0x40
  #define ADM1026_VERSTEP_ADM1026		0x44
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154

cb01a2312   Jean Delvare   hwmon: (adm1026) ...
155
156
157
158
  #define ADM1026_REG_MASK1		0x18
  #define ADM1026_REG_MASK2		0x19
  #define ADM1026_REG_MASK3		0x1a
  #define ADM1026_REG_MASK4		0x1b
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159

cb01a2312   Jean Delvare   hwmon: (adm1026) ...
160
161
162
163
  #define ADM1026_REG_STATUS1		0x20
  #define ADM1026_REG_STATUS2		0x21
  #define ADM1026_REG_STATUS3		0x22
  #define ADM1026_REG_STATUS4		0x23
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  
  #define ADM1026_FAN_ACTIVATION_TEMP_HYST -6
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
166
167
  #define ADM1026_FAN_CONTROL_TEMP_RANGE	20
  #define ADM1026_PWM_MAX			255
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

cb01a2312   Jean Delvare   hwmon: (adm1026) ...
169
  /* Conversions. Rounding and limit checking is only done on the TO_REG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
   * variants. Note that you should be a bit careful with which arguments
   * these macros are called: arguments may be evaluated more than once.
   */
25985edce   Lucas De Marchi   Fix common misspe...
173
  /* IN are scaled according to built-in resistors.  These are the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
180
181
182
183
   *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
   *   NOTE: The -12V input needs an additional factor to account
   *      for the Vref pullup resistor.
   *      NEG12_OFFSET = SCALE * Vref / V-192 - Vref
   *                   = 13875 * 2.50 / 1.875 - 2500
   *                   = 16000
   *
   * The values in this table are based on Table II, page 15 of the
   *    datasheet.
   */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
184
185
186
  static int adm1026_scaling[] = { /* .001 Volts */
  		2250, 2250, 2250, 2250, 2250, 2250,
  		1875, 1875, 1875, 1875, 3000, 3330,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
  		3330, 4995, 2250, 12000, 13875
  	};
  #define NEG12_OFFSET  16000
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
190
191
192
193
  #define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
  #define INS_TO_REG(n, val)  (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\
  	0, 255))
  #define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
  
  /* FAN speed is measured using 22.5kHz clock and counts for 2 pulses
   *   and we assume a 2 pulse-per-rev fan tach signal
   *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
   */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
199
200
201
202
  #define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
  				SENSORS_LIMIT(1350000/((val)*(div)), 1, 254))
  #define FAN_FROM_REG(val, div) ((val) == 0 ? -1:(val) == 0xff ? 0 : \
  				1350000/((val)*(div)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  #define DIV_FROM_REG(val) (1<<(val))
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
204
  #define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
  
  /* Temperature is reported in 1 degC increments */
  #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
208
  	-127, 127))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
  #define TEMP_FROM_REG(val) ((val) * 1000)
  #define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
211
  	-127, 127))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  #define OFFSET_FROM_REG(val) ((val) * 1000)
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
213
  #define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
  #define PWM_FROM_REG(val) (val)
  
  #define PWM_MIN_TO_REG(val) ((val) & 0xf0)
  #define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4))
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
218
219
  /* Analog output is a voltage, and scaled to millivolts.  The datasheet
   *   indicates that the DAC could be used to drive the fans, but in our
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
   *   example board (Arima HDAMA) it isn't connected to the fans at all.
   */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
222
  #define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  #define DAC_FROM_REG(val) (((val)*2500)/255)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
230
231
232
233
234
  /* Chip sampling rates
   *
   * Some sensors are not updated more frequently than once per second
   *    so it doesn't make sense to read them more often than that.
   *    We cache the results and return the saved data if the driver
   *    is called again before a second has elapsed.
   *
   * Also, there is significant configuration data for this chip
   *    So, we keep the config data up to date in the cache
   *    when it is written and only sample it once every 5 *minutes*
   */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
235
236
  #define ADM1026_DATA_INTERVAL		(1 * HZ)
  #define ADM1026_CONFIG_INTERVAL		(5 * 60 * HZ)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  
  /* We allow for multiple chips in a single system.
   *
   * For each registered ADM1026, we need to keep state information
   * at client->data. The adm1026_data structure is dynamically
   * allocated, when a new client structure is allocated. */
  
  struct pwm_data {
  	u8 pwm;
  	u8 enable;
  	u8 auto_pwm_min;
  };
  
  struct adm1026_data {
1beeffe43   Tony Jones   hwmon: Convert fr...
251
  	struct device *hwmon_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
253
  	struct mutex update_lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
  	int valid;		/* !=0 if following fields are valid */
  	unsigned long last_reading;	/* In jiffies */
  	unsigned long last_config;	/* In jiffies */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
257
258
259
260
261
262
263
264
265
266
267
268
269
  	u8 in[17];		/* Register value */
  	u8 in_max[17];		/* Register value */
  	u8 in_min[17];		/* Register value */
  	s8 temp[3];		/* Register value */
  	s8 temp_min[3];		/* Register value */
  	s8 temp_max[3];		/* Register value */
  	s8 temp_tmin[3];	/* Register value */
  	s8 temp_crit[3];	/* Register value */
  	s8 temp_offset[3];	/* Register value */
  	u8 fan[8];		/* Register value */
  	u8 fan_min[8];		/* Register value */
  	u8 fan_div[8];		/* Decoded value */
  	struct pwm_data pwm1;	/* Pwm control values */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
270
  	u8 vrm;			/* VRM version */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  	u8 analog_out;		/* Register value (DAC) */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
272
273
274
275
276
277
278
279
  	long alarms;		/* Register encoding, combined */
  	long alarm_mask;	/* Register encoding, combined */
  	long gpio;		/* Register encoding, combined */
  	long gpio_mask;		/* Register encoding, combined */
  	u8 gpio_config[17];	/* Decoded value */
  	u8 config1;		/* Register value */
  	u8 config2;		/* Register value */
  	u8 config3;		/* Register value */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  };
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
281
282
  static int adm1026_probe(struct i2c_client *client,
  			 const struct i2c_device_id *id);
310ec7921   Jean Delvare   i2c: Drop the kin...
283
  static int adm1026_detect(struct i2c_client *client,
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
284
285
  			  struct i2c_board_info *info);
  static int adm1026_remove(struct i2c_client *client);
f6c27fc17   Darren Jenkins   [PATCH] I2C: hwmo...
286
287
  static int adm1026_read_value(struct i2c_client *client, u8 reg);
  static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  static void adm1026_print_gpio(struct i2c_client *client);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
289
  static void adm1026_fixup_gpio(struct i2c_client *client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
  static struct adm1026_data *adm1026_update_device(struct device *dev);
  static void adm1026_init_client(struct i2c_client *client);
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
292
  static const struct i2c_device_id adm1026_id[] = {
1f86df49d   Jean Delvare   i2c: Drop I2C_CLI...
293
  	{ "adm1026", 0 },
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
294
295
296
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, adm1026_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  static struct i2c_driver adm1026_driver = {
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
298
  	.class		= I2C_CLASS_HWMON,
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
299
  	.driver = {
cdaf79349   Laurent Riffard   [PATCH] i2c: Drop...
300
301
  		.name	= "adm1026",
  	},
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
302
303
304
305
  	.probe		= adm1026_probe,
  	.remove		= adm1026_remove,
  	.id_table	= adm1026_id,
  	.detect		= adm1026_detect,
c3813d6af   Jean Delvare   i2c: Get rid of s...
306
  	.address_list	= normal_i2c,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  };
c49efceff   Ben Dooks   [PATCH] hwmon: St...
308
  static int adm1026_read_value(struct i2c_client *client, u8 reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
314
315
316
317
318
319
320
  {
  	int res;
  
  	if (reg < 0x80) {
  		/* "RAM" locations */
  		res = i2c_smbus_read_byte_data(client, reg) & 0xff;
  	} else {
  		/* EEPROM, do nothing */
  		res = 0;
  	}
  	return res;
  }
c49efceff   Ben Dooks   [PATCH] hwmon: St...
321
  static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
327
328
329
330
331
332
333
  {
  	int res;
  
  	if (reg < 0x80) {
  		/* "RAM" locations */
  		res = i2c_smbus_write_byte_data(client, reg, value);
  	} else {
  		/* EEPROM, do nothing */
  		res = 0;
  	}
  	return res;
  }
c49efceff   Ben Dooks   [PATCH] hwmon: St...
334
  static void adm1026_init_client(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
  {
  	int value, i;
  	struct adm1026_data *data = i2c_get_clientdata(client);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
338
339
  	dev_dbg(&client->dev, "Initializing device
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  	/* Read chip config */
  	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
  	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
  	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
  
  	/* Inform user of chip config */
  	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x
  ",
  		data->config1);
  	if ((data->config1 & CFG1_MONITOR) == 0) {
  		dev_dbg(&client->dev, "Monitoring not currently "
  			"enabled.
  ");
  	}
  	if (data->config1 & CFG1_INT_ENABLE) {
  		dev_dbg(&client->dev, "SMBALERT interrupts are "
  			"enabled.
  ");
  	}
  	if (data->config1 & CFG1_AIN8_9) {
  		dev_dbg(&client->dev, "in8 and in9 enabled. "
  			"temp3 disabled.
  ");
  	} else {
  		dev_dbg(&client->dev, "temp3 enabled.  in8 and "
  			"in9 disabled.
  ");
  	}
  	if (data->config1 & CFG1_THERM_HOT) {
  		dev_dbg(&client->dev, "Automatic THERM, PWM, "
  			"and temp limits enabled.
  ");
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	if (data->config3 & CFG3_GPIO16_ENABLE) {
368609c5a   Jean Delvare   [PATCH] I2C: Miss...
374
  		dev_dbg(&client->dev, "GPIO16 enabled.  THERM "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  			"pin disabled.
  ");
  	} else {
  		dev_dbg(&client->dev, "THERM pin enabled.  "
  			"GPIO16 disabled.
  ");
  	}
  	if (data->config3 & CFG3_VREF_250) {
  		dev_dbg(&client->dev, "Vref is 2.50 Volts.
  ");
  	} else {
  		dev_dbg(&client->dev, "Vref is 1.82 Volts.
  ");
  	}
  	/* Read and pick apart the existing GPIO configuration */
  	value = 0;
  	for (i = 0;i <= 15;++i) {
  		if ((i & 0x03) == 0) {
  			value = adm1026_read_value(client,
  					ADM1026_REG_GPIO_CFG_0_3 + i/4);
  		}
  		data->gpio_config[i] = value & 0x03;
  		value >>= 2;
  	}
  	data->gpio_config[16] = (data->config3 >> 6) & 0x03;
  
  	/* ... and then print it */
  	adm1026_print_gpio(client);
  
  	/* If the user asks us to reprogram the GPIO config, then
  	 * do it now.
  	 */
  	if (gpio_input[0] != -1 || gpio_output[0] != -1
  		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
  		|| gpio_fan[0] != -1) {
  		adm1026_fixup_gpio(client);
  	}
  
  	/* WE INTENTIONALLY make no changes to the limits,
  	 *   offsets, pwms, fans and zones.  If they were
  	 *   configured, we don't want to mess with them.
  	 *   If they weren't, the default is 100% PWM, no
  	 *   control and will suffice until 'sensors -s'
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
418
  	 *   can be run by the user.  We DO set the default
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  	 *   value for pwm1.auto_pwm_min to its maximum
  	 *   so that enabling automatic pwm fan control
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
421
  	 *   without first setting a value for pwm1.auto_pwm_min
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  	 *   will not result in potentially dangerous fan speed decrease.
  	 */
  	data->pwm1.auto_pwm_min=255;
  	/* Start monitoring */
  	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
  	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
  	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
  	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x
  ", value);
  	data->config1 = value;
  	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
  
  	/* initialize fan_div[] to hardware defaults */
  	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
  		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
  	for (i = 0;i <= 7;++i) {
  		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
  		value >>= 2;
  	}
  }
c49efceff   Ben Dooks   [PATCH] hwmon: St...
442
  static void adm1026_print_gpio(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
  {
  	struct adm1026_data *data = i2c_get_clientdata(client);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
445
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

885fe4b1f   Jean Delvare   hwmon: (adm1026) ...
447
448
  	dev_dbg(&client->dev, "GPIO config is:
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  	for (i = 0;i <= 7;++i) {
  		if (data->config2 & (1 << i)) {
  			dev_dbg(&client->dev, "\t%sGP%s%d
  ",
  				data->gpio_config[i] & 0x02 ? "" : "!",
  				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
  				i);
  		} else {
  			dev_dbg(&client->dev, "\tFAN%d
  ", i);
  		}
  	}
  	for (i = 8;i <= 15;++i) {
  		dev_dbg(&client->dev, "\t%sGP%s%d
  ",
  			data->gpio_config[i] & 0x02 ? "" : "!",
  			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
  			i);
  	}
  	if (data->config3 & CFG3_GPIO16_ENABLE) {
  		dev_dbg(&client->dev, "\t%sGP%s16
  ",
  			data->gpio_config[16] & 0x02 ? "" : "!",
  			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
  	} else {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
474
  		/* GPIO16 is THERM */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
  		dev_dbg(&client->dev, "\tTHERM
  ");
  	}
  }
c49efceff   Ben Dooks   [PATCH] hwmon: St...
479
  static void adm1026_fixup_gpio(struct i2c_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
  {
  	struct adm1026_data *data = i2c_get_clientdata(client);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
482
483
  	int i;
  	int value;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  
  	/* Make the changes requested. */
  	/* We may need to unlock/stop monitoring or soft-reset the
  	 *    chip before we can make changes.  This hasn't been
  	 *    tested much.  FIXME
  	 */
  
  	/* Make outputs */
  	for (i = 0;i <= 16;++i) {
  		if (gpio_output[i] >= 0 && gpio_output[i] <= 16) {
  			data->gpio_config[gpio_output[i]] |= 0x01;
  		}
  		/* if GPIO0-7 is output, it isn't a FAN tach */
  		if (gpio_output[i] >= 0 && gpio_output[i] <= 7) {
  			data->config2 |= 1 << gpio_output[i];
  		}
  	}
  
  	/* Input overrides output */
  	for (i = 0;i <= 16;++i) {
  		if (gpio_input[i] >= 0 && gpio_input[i] <= 16) {
  			data->gpio_config[gpio_input[i]] &= ~ 0x01;
  		}
  		/* if GPIO0-7 is input, it isn't a FAN tach */
  		if (gpio_input[i] >= 0 && gpio_input[i] <= 7) {
  			data->config2 |= 1 << gpio_input[i];
  		}
  	}
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
512
  	/* Inverted */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
515
516
517
  	for (i = 0;i <= 16;++i) {
  		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) {
  			data->gpio_config[gpio_inverted[i]] &= ~ 0x02;
  		}
  	}
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
518
  	/* Normal overrides inverted */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
  	for (i = 0;i <= 16;++i) {
  		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) {
  			data->gpio_config[gpio_normal[i]] |= 0x02;
  		}
  	}
  
  	/* Fan overrides input and output */
  	for (i = 0;i <= 7;++i) {
  		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) {
  			data->config2 &= ~(1 << gpio_fan[i]);
  		}
  	}
  
  	/* Write new configs to registers */
  	adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
  	data->config3 = (data->config3 & 0x3f)
  			| ((data->gpio_config[16] & 0x03) << 6);
  	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
  	for (i = 15, value = 0;i >= 0;--i) {
  		value <<= 2;
  		value |= data->gpio_config[i] & 0x03;
  		if ((i & 0x03) == 0) {
  			adm1026_write_value(client,
  					ADM1026_REG_GPIO_CFG_0_3 + i/4,
  					value);
  			value = 0;
  		}
  	}
  
  	/* Print the new config */
  	adm1026_print_gpio(client);
  }
  
  
  static struct adm1026_data *adm1026_update_device(struct device *dev)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int i;
  	long value, alarms, gpio;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
559
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
561
562
  	if (!data->valid
  	    || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
  		/* Things that change quickly */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
563
564
  		dev_dbg(&client->dev, "Reading sensor values
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
567
568
569
570
571
572
573
574
575
576
  		for (i = 0;i <= 16;++i) {
  			data->in[i] =
  			    adm1026_read_value(client, ADM1026_REG_IN[i]);
  		}
  
  		for (i = 0;i <= 7;++i) {
  			data->fan[i] =
  			    adm1026_read_value(client, ADM1026_REG_FAN(i));
  		}
  
  		for (i = 0;i <= 2;++i) {
  			/* NOTE: temp[] is s8 and we assume 2's complement
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
577
  			 *   "conversion" in the assignment */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
580
  			data->temp[i] =
  			    adm1026_read_value(client, ADM1026_REG_TEMP[i]);
  		}
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
581
  		data->pwm1.pwm = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  			ADM1026_REG_PWM);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
583
  		data->analog_out = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
586
  			ADM1026_REG_DAC);
  		/* GPIO16 is MSbit of alarms, move it to gpio */
  		alarms = adm1026_read_value(client, ADM1026_REG_STATUS4);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
587
  		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
592
593
594
595
596
597
  		alarms &= 0x7f;
  		alarms <<= 8;
  		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3);
  		alarms <<= 8;
  		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2);
  		alarms <<= 8;
  		alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1);
  		data->alarms = alarms;
  
  		/* Read the GPIO values */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
598
  		gpio |= adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
  			ADM1026_REG_GPIO_STATUS_8_15);
  		gpio <<= 8;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
601
  		gpio |= adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
603
604
605
  			ADM1026_REG_GPIO_STATUS_0_7);
  		data->gpio = gpio;
  
  		data->last_reading = jiffies;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
606
  	}; /* last_reading */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
609
610
611
612
613
  
  	if (!data->valid ||
  	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
  		/* Things that don't change often */
  		dev_dbg(&client->dev, "Reading config values
  ");
  		for (i = 0;i <= 16;++i) {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
614
  			data->in_min[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  				ADM1026_REG_IN_MIN[i]);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
616
  			data->in_max[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
621
622
623
  				ADM1026_REG_IN_MAX[i]);
  		}
  
  		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
  			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
  			<< 8);
  		for (i = 0;i <= 7;++i) {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
624
  			data->fan_min[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
627
628
629
630
  				ADM1026_REG_FAN_MIN(i));
  			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
  			value >>= 2;
  		}
  
  		for (i = 0; i <= 2; ++i) {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
631
  			/* NOTE: temp_xxx[] are s8 and we assume 2's
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
  			 *    complement "conversion" in the assignment
  			 */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
634
  			data->temp_min[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  				ADM1026_REG_TEMP_MIN[i]);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
636
  			data->temp_max[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  				ADM1026_REG_TEMP_MAX[i]);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
638
  			data->temp_tmin[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  				ADM1026_REG_TEMP_TMIN[i]);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
640
  			data->temp_crit[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
  				ADM1026_REG_TEMP_THERM[i]);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
642
  			data->temp_offset[i] = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
646
  				ADM1026_REG_TEMP_OFFSET[i]);
  		}
  
  		/* Read the STATUS/alarm masks */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
647
648
649
  		alarms = adm1026_read_value(client, ADM1026_REG_MASK4);
  		gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */
  		alarms = (alarms & 0x7f) << 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
652
653
654
655
656
657
  		alarms |= adm1026_read_value(client, ADM1026_REG_MASK3);
  		alarms <<= 8;
  		alarms |= adm1026_read_value(client, ADM1026_REG_MASK2);
  		alarms <<= 8;
  		alarms |= adm1026_read_value(client, ADM1026_REG_MASK1);
  		data->alarm_mask = alarms;
  
  		/* Read the GPIO values */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
658
  		gpio |= adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
663
664
  			ADM1026_REG_GPIO_MASK_8_15);
  		gpio <<= 8;
  		gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7);
  		data->gpio_mask = gpio;
  
  		/* Read various values from CONFIG1 */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
665
  		data->config1 = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
  			ADM1026_REG_CONFIG1);
  		if (data->config1 & CFG1_PWM_AFC) {
  			data->pwm1.enable = 2;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
669
  			data->pwm1.auto_pwm_min =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
671
672
  				PWM_MIN_FROM_REG(data->pwm1.pwm);
  		}
  		/* Read the GPIO config */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
673
  		data->config2 = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  			ADM1026_REG_CONFIG2);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
675
  		data->config3 = adm1026_read_value(client,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
680
681
682
683
684
685
686
687
688
689
  			ADM1026_REG_CONFIG3);
  		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
  
  		value = 0;
  		for (i = 0;i <= 15;++i) {
  			if ((i & 0x03) == 0) {
  				value = adm1026_read_value(client,
  					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
  			}
  			data->gpio_config[i] = value & 0x03;
  			value >>= 2;
  		}
  
  		data->last_config = jiffies;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
690
  	}; /* last_config */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  	data->valid = 1;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
693
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
  	return data;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
696
697
  static ssize_t show_in(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
699
700
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
702
703
  	return sprintf(buf, "%d
  ", INS_FROM_REG(nr, data->in[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
705
706
  static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
708
709
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
710
711
712
  	struct adm1026_data *data = adm1026_update_device(dev);
  	return sprintf(buf, "%d
  ", INS_FROM_REG(nr, data->in_min[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
714
715
  static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
717
718
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
722
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
  	data->in_min[nr] = INS_TO_REG(nr, val);
  	adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
725
  	mutex_unlock(&data->update_lock);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
726
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
728
729
  static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
731
732
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
734
735
  	return sprintf(buf, "%d
  ", INS_FROM_REG(nr, data->in_max[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
737
738
  static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
740
741
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
745
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
  	data->in_max[nr] = INS_TO_REG(nr, val);
  	adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
748
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
751
752
753
754
755
756
757
  #define in_reg(offset)						\
  static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,	\
  		NULL, offset);					\
  static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
  		show_in_min, set_in_min, offset);		\
  static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
  		show_in_max, set_in_max, offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
  
  
  in_reg(0);
  in_reg(1);
  in_reg(2);
  in_reg(3);
  in_reg(4);
  in_reg(5);
  in_reg(6);
  in_reg(7);
  in_reg(8);
  in_reg(9);
  in_reg(10);
  in_reg(11);
  in_reg(12);
  in_reg(13);
  in_reg(14);
  in_reg(15);
74880c063   Yani Ioannou   [PATCH] Driver Co...
776
  static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
778
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
779
780
  	return sprintf(buf, "%d
  ", INS_FROM_REG(16, data->in[16]) -
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
  		NEG12_OFFSET);
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
783
  static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
785
786
787
  	struct adm1026_data *data = adm1026_update_device(dev);
  	return sprintf(buf, "%d
  ", INS_FROM_REG(16, data->in_min[16])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
  		- NEG12_OFFSET);
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
790
  static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
793
794
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
795
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
797
  	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
  	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
798
  	mutex_unlock(&data->update_lock);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
799
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
801
  static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
804
805
  	return sprintf(buf, "%d
  ", INS_FROM_REG(16, data->in_max[16])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
  			- NEG12_OFFSET);
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
808
  static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
811
812
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
813
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
815
  	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
  	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
816
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
819
820
821
  static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
  static SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16);
  static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
824
825
826
  
  
  
  
  /* Now add fan read/write functions */
050480f12   Yani Ioannou   [PATCH] I2C: driv...
827
828
  static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
830
831
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
833
834
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan[nr],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
  		data->fan_div[nr]));
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
837
838
  static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
840
841
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
843
844
  	return sprintf(buf, "%d
  ", FAN_FROM_REG(data->fan_min[nr],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
  		data->fan_div[nr]));
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
847
848
  static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
850
851
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
854
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
855
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
  	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
  	adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr),
  		data->fan_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
859
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
  	return count;
  }
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
862
863
864
865
  #define fan_offset(offset)						\
  static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL,	\
  		offset - 1);						\
  static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
050480f12   Yani Ioannou   [PATCH] I2C: driv...
866
  		show_fan_min, set_fan_min, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
  
  fan_offset(1);
  fan_offset(2);
  fan_offset(3);
  fan_offset(4);
  fan_offset(5);
  fan_offset(6);
  fan_offset(7);
  fan_offset(8);
  
  /* Adjust fan_min to account for new fan divisor */
  static void fixup_fan_min(struct device *dev, int fan, int old_div)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
882
883
  	int new_min;
  	int new_div = data->fan_div[fan];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
886
887
888
889
890
891
892
893
894
895
896
  
  	/* 0 and 0xff are special.  Don't adjust them */
  	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) {
  		return;
  	}
  
  	new_min = data->fan_min[fan] * old_div / new_div;
  	new_min = SENSORS_LIMIT(new_min, 1, 254);
  	data->fan_min[fan] = new_min;
  	adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
  }
  
  /* Now add fan_div read/write functions */
050480f12   Yani Ioannou   [PATCH] I2C: driv...
897
898
  static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
900
901
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
903
904
  	return sprintf(buf, "%d
  ", data->fan_div[nr]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
906
907
  static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
909
910
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
52bc9802c   Gabriele Gorla   hwmon: (adm1026) ...
913
  	int val, orig_div, new_div;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
  
  	val = simple_strtol(buf, NULL, 10);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
916
  	new_div = DIV_TO_REG(val);
8b0f1840a   Gabriele Gorla   hwmon: (adm1026) ...
917

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
918
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
922
  	orig_div = data->fan_div[nr];
  	data->fan_div[nr] = DIV_FROM_REG(new_div);
  
  	if (nr < 4) { /* 0 <= nr < 4 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
  		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
52bc9802c   Gabriele Gorla   hwmon: (adm1026) ...
924
925
926
927
  				    (DIV_TO_REG(data->fan_div[0]) << 0) |
  				    (DIV_TO_REG(data->fan_div[1]) << 2) |
  				    (DIV_TO_REG(data->fan_div[2]) << 4) |
  				    (DIV_TO_REG(data->fan_div[3]) << 6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  	} else { /* 3 < nr < 8 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
  		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
52bc9802c   Gabriele Gorla   hwmon: (adm1026) ...
930
931
932
933
  				    (DIV_TO_REG(data->fan_div[4]) << 0) |
  				    (DIV_TO_REG(data->fan_div[5]) << 2) |
  				    (DIV_TO_REG(data->fan_div[6]) << 4) |
  				    (DIV_TO_REG(data->fan_div[7]) << 6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
  	}
  
  	if (data->fan_div[nr] != orig_div) {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
937
  		fixup_fan_min(dev, nr, orig_div);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
939
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
  	return count;
  }
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
942
943
  #define fan_offset_div(offset)						\
  static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
050480f12   Yani Ioannou   [PATCH] I2C: driv...
944
  		show_fan_div, set_fan_div, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
946
947
948
949
950
951
952
953
954
955
  
  fan_offset_div(1);
  fan_offset_div(2);
  fan_offset_div(3);
  fan_offset_div(4);
  fan_offset_div(5);
  fan_offset_div(6);
  fan_offset_div(7);
  fan_offset_div(8);
  
  /* Temps */
050480f12   Yani Ioannou   [PATCH] I2C: driv...
956
957
  static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
959
960
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
962
963
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
965
966
  static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
968
969
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
971
972
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_min[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
974
975
  static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
977
978
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
981
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
982
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
985
  	data->temp_min[nr] = TEMP_TO_REG(val);
  	adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr],
  		data->temp_min[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
986
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
989
990
  static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
  		char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
992
993
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
995
996
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_max[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
998
999
  static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1001
1002
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
1005
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1006
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
  	data->temp_max[nr] = TEMP_TO_REG(val);
  	adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr],
  		data->temp_max[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1010
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
1012
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1013
1014
  
  #define temp_reg(offset)						\
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1015
  static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,	\
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1016
1017
1018
1019
1020
  		NULL, offset - 1);					\
  static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
  		show_temp_min, set_temp_min, offset - 1);		\
  static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
  		show_temp_max, set_temp_max, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
1022
1023
1024
1025
  
  
  temp_reg(1);
  temp_reg(2);
  temp_reg(3);
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1026
1027
  static ssize_t show_temp_offset(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1029
1030
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1032
1033
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_offset[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1035
1036
1037
  static ssize_t set_temp_offset(struct device *dev,
  		struct device_attribute *attr, const char *buf,
  		size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1039
1040
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
1042
1043
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1044
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
1047
  	data->temp_offset[nr] = TEMP_TO_REG(val);
  	adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr],
  		data->temp_offset[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1048
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
1050
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1051
1052
1053
  #define temp_offset_reg(offset)							\
  static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,		\
  		show_temp_offset, set_temp_offset, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
1055
1056
1057
  
  temp_offset_reg(1);
  temp_offset_reg(2);
  temp_offset_reg(3);
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1058
1059
  static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1061
1062
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1064
1065
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
1067
  		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1068
1069
  static ssize_t show_temp_auto_point2_temp(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1071
1072
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1074
1075
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_tmin[nr] +
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
  		ADM1026_FAN_CONTROL_TEMP_RANGE));
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1078
1079
  static ssize_t show_temp_auto_point1_temp(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1081
1082
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1084
1085
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_tmin[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1087
1088
  static ssize_t set_temp_auto_point1_temp(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1090
1091
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
1093
1094
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1095
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
1098
  	data->temp_tmin[nr] = TEMP_TO_REG(val);
  	adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr],
  		data->temp_tmin[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1099
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
1101
  	return count;
  }
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1102
1103
1104
1105
1106
1107
1108
  #define temp_auto_point(offset)						\
  static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp,		\
  		S_IRUGO | S_IWUSR, show_temp_auto_point1_temp,		\
  		set_temp_auto_point1_temp, offset - 1);			\
  static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\
  		show_temp_auto_point1_temp_hyst, NULL, offset - 1);	\
  static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,	\
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1109
  		show_temp_auto_point2_temp, NULL, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
1111
1112
1113
  
  temp_auto_point(1);
  temp_auto_point(2);
  temp_auto_point(3);
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1114
1115
  static ssize_t show_temp_crit_enable(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1118
1119
  	return sprintf(buf, "%d
  ", (data->config1 & CFG1_THERM_HOT) >> 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1121
1122
  static ssize_t set_temp_crit_enable(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
1124
1125
1126
1127
1128
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
  
  	if ((val == 1) || (val==0)) {
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1129
  		mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
  		data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1131
  		adm1026_write_value(client, ADM1026_REG_CONFIG1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  			data->config1);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1133
  		mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
1135
1136
  	}
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1137
1138
  #define temp_crit_enable(offset)				\
  static DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
  	show_temp_crit_enable, set_temp_crit_enable);
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1140
1141
1142
  temp_crit_enable(1);
  temp_crit_enable(2);
  temp_crit_enable(3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143

050480f12   Yani Ioannou   [PATCH] I2C: driv...
1144
1145
  static ssize_t show_temp_crit(struct device *dev,
  		struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1147
1148
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1150
1151
  	return sprintf(buf, "%d
  ", TEMP_FROM_REG(data->temp_crit[nr]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1153
1154
  static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
  		const char *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
  {
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1156
1157
  	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
  	int nr = sensor_attr->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
1160
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1161
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
1164
  	data->temp_crit[nr] = TEMP_TO_REG(val);
  	adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr],
  		data->temp_crit[nr]);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1165
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
  	return count;
  }
050480f12   Yani Ioannou   [PATCH] I2C: driv...
1168
1169
1170
  #define temp_crit_reg(offset)						\
  static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
  		show_temp_crit, set_temp_crit, offset - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
1172
1173
1174
  
  temp_crit_reg(1);
  temp_crit_reg(2);
  temp_crit_reg(3);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1175
  static ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
1177
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1178
1179
  	return sprintf(buf, "%d
  ", DAC_FROM_REG(data->analog_out));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1181
  static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
1183
1184
1185
1186
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1187
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
  	data->analog_out = DAC_TO_REG(val);
  	adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1190
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
  	return count;
  }
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1193
  static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
  	set_analog_out_reg);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1195
  static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196
1197
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
a0cf354a7   Jean Delvare   hwmon: (adm1026) ...
1198
1199
1200
1201
1202
1203
  	int vid = (data->gpio >> 11) & 0x1f;
  
  	dev_dbg(dev, "Setting VID from GPIO11-15.
  ");
  	return sprintf(buf, "%d
  ", vid_from_reg(vid, data->vrm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
  }
937df8df9   Grant Coady   [PATCH] I2C: sysf...
1205
  static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206

74880c063   Yani Ioannou   [PATCH] Driver Co...
1207
  static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  {
90d6619a9   Jean Delvare   hwmon: VRM is not...
1209
  	struct adm1026_data *data = dev_get_drvdata(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1210
1211
  	return sprintf(buf, "%d
  ", data->vrm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1213
  static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
  		size_t count)
  {
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1216
  	struct adm1026_data *data = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
1218
1219
1220
1221
1222
  
  	data->vrm = simple_strtol(buf, NULL, 10);
  	return count;
  }
  
  static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1223
  static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
1225
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1226
1227
  	return sprintf(buf, "%ld
  ", data->alarms);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
1229
1230
  }
  
  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
  static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
  			  char *buf)
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
  	int bitnr = to_sensor_dev_attr(attr)->index;
  	return sprintf(buf, "%ld
  ", (data->alarms >> bitnr) & 1);
  }
  
  static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2);
  static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4);
  static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5);
  static SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6);
  static SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7);
  static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8);
  static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9);
  static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10);
  static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11);
  static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12);
  static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13);
  static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14);
  static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15);
  static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
  static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
  static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
  static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19);
  static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20);
  static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21);
  static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22);
  static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23);
  static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24);
  static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25);
  static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1268
  static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
1270
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1271
1272
  	return sprintf(buf, "%ld
  ", data->alarm_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1274
  static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1275
1276
1277
1278
1279
1280
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
  	unsigned long mask;
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1281
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  	data->alarm_mask = val & 0x7fffffff;
  	mask = data->alarm_mask
  		| (data->gpio_mask & 0x10000 ? 0x80000000 : 0);
  	adm1026_write_value(client, ADM1026_REG_MASK1,
  		mask & 0xff);
  	mask >>= 8;
  	adm1026_write_value(client, ADM1026_REG_MASK2,
  		mask & 0xff);
  	mask >>= 8;
  	adm1026_write_value(client, ADM1026_REG_MASK3,
  		mask & 0xff);
  	mask >>= 8;
  	adm1026_write_value(client, ADM1026_REG_MASK4,
  		mask & 0xff);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1296
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
1298
1299
1300
1301
  	return count;
  }
  
  static DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
  	set_alarm_mask);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1302
  static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
1304
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1305
1306
  	return sprintf(buf, "%ld
  ", data->gpio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1308
  static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
1310
1311
1312
1313
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1314
  	long gpio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1316
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
  	data->gpio = val & 0x1ffff;
  	gpio = data->gpio;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1319
  	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  	gpio >>= 8;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1321
  	adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
  	gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1323
  	adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1324
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
1328
  	return count;
  }
  
  static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1329
  static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
1331
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1332
1333
  	return sprintf(buf, "%ld
  ", data->gpio_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1335
  static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
1337
1338
1339
1340
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1341
  	long mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1342

9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1343
  	mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
1345
  	data->gpio_mask = val & 0x1ffff;
  	mask = data->gpio_mask;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1346
  	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
  	mask >>= 8;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1348
  	adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
  	mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1350
  	adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1351
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
1354
1355
  	return count;
  }
  
  static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
74880c063   Yani Ioannou   [PATCH] Driver Co...
1356
  static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1359
1360
  	return sprintf(buf, "%d
  ", PWM_FROM_REG(data->pwm1.pwm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1362
  static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
1367
1368
1369
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  
  	if (data->pwm1.enable == 1) {
  		int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1370
  		mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
  		data->pwm1.pwm = PWM_TO_REG(val);
  		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1373
  		mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
1375
1376
  	}
  	return count;
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1377
  static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
1379
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1380
1381
  	return sprintf(buf, "%d
  ", data->pwm1.auto_pwm_min);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1383
  static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
1385
1386
1387
1388
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1389
  	mutex_lock(&data->update_lock);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1390
  	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
  	if (data->pwm1.enable == 2) { /* apply immediately */
  		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1393
  			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
  		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
  	}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1396
  	mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
  	return count;
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1399
  static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
  {
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1401
1402
  	return sprintf(buf, "%d
  ", ADM1026_PWM_MAX);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1404
  static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
  {
  	struct adm1026_data *data = adm1026_update_device(dev);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1407
1408
  	return sprintf(buf, "%d
  ", data->pwm1.enable);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
  }
74880c063   Yani Ioannou   [PATCH] Driver Co...
1410
  static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
1412
1413
1414
1415
  		size_t count)
  {
  	struct i2c_client *client = to_i2c_client(dev);
  	struct adm1026_data *data = i2c_get_clientdata(client);
  	int val = simple_strtol(buf, NULL, 10);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1416
  	int old_enable;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
1418
  
  	if ((val >= 0) && (val < 3)) {
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1419
  		mutex_lock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
1421
1422
1423
1424
1425
  		old_enable = data->pwm1.enable;
  		data->pwm1.enable = val;
  		data->config1 = (data->config1 & ~CFG1_PWM_AFC)
  				| ((val == 2) ? CFG1_PWM_AFC : 0);
  		adm1026_write_value(client, ADM1026_REG_CONFIG1,
  			data->config1);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1426
  		if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
  			data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1428
1429
  				PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
  			adm1026_write_value(client, ADM1026_REG_PWM,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
1431
1432
1433
  				data->pwm1.pwm);
  		} else if (!((old_enable == 1) && (val == 1))) {
  			/* set pwm to safe value */
  			data->pwm1.pwm = 255;
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1434
  			adm1026_write_value(client, ADM1026_REG_PWM,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
1436
  				data->pwm1.pwm);
  		}
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1437
  		mutex_unlock(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
1440
1441
1442
  	}
  	return count;
  }
  
  /* enable PWM fan control */
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1443
1444
1445
1446
  static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
  static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
  static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg);
  static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
  	set_pwm_enable);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1448
  static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449
  	set_pwm_enable);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1450
  static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
  	set_pwm_enable);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1452
  static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
  	show_auto_pwm_min, set_auto_pwm_min);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1454
  static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
  	show_auto_pwm_min, set_auto_pwm_min);
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1456
  static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
1458
1459
1460
1461
  	show_auto_pwm_min, set_auto_pwm_min);
  
  static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
  static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
  static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1462
1463
1464
1465
  static struct attribute *adm1026_attributes[] = {
  	&sensor_dev_attr_in0_input.dev_attr.attr,
  	&sensor_dev_attr_in0_max.dev_attr.attr,
  	&sensor_dev_attr_in0_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1466
  	&sensor_dev_attr_in0_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1467
1468
1469
  	&sensor_dev_attr_in1_input.dev_attr.attr,
  	&sensor_dev_attr_in1_max.dev_attr.attr,
  	&sensor_dev_attr_in1_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1470
  	&sensor_dev_attr_in1_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1471
1472
1473
  	&sensor_dev_attr_in2_input.dev_attr.attr,
  	&sensor_dev_attr_in2_max.dev_attr.attr,
  	&sensor_dev_attr_in2_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1474
  	&sensor_dev_attr_in2_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1475
1476
1477
  	&sensor_dev_attr_in3_input.dev_attr.attr,
  	&sensor_dev_attr_in3_max.dev_attr.attr,
  	&sensor_dev_attr_in3_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1478
  	&sensor_dev_attr_in3_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1479
1480
1481
  	&sensor_dev_attr_in4_input.dev_attr.attr,
  	&sensor_dev_attr_in4_max.dev_attr.attr,
  	&sensor_dev_attr_in4_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1482
  	&sensor_dev_attr_in4_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1483
1484
1485
  	&sensor_dev_attr_in5_input.dev_attr.attr,
  	&sensor_dev_attr_in5_max.dev_attr.attr,
  	&sensor_dev_attr_in5_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1486
  	&sensor_dev_attr_in5_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1487
1488
1489
  	&sensor_dev_attr_in6_input.dev_attr.attr,
  	&sensor_dev_attr_in6_max.dev_attr.attr,
  	&sensor_dev_attr_in6_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1490
  	&sensor_dev_attr_in6_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1491
1492
1493
  	&sensor_dev_attr_in7_input.dev_attr.attr,
  	&sensor_dev_attr_in7_max.dev_attr.attr,
  	&sensor_dev_attr_in7_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1494
  	&sensor_dev_attr_in7_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1495
1496
1497
  	&sensor_dev_attr_in10_input.dev_attr.attr,
  	&sensor_dev_attr_in10_max.dev_attr.attr,
  	&sensor_dev_attr_in10_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1498
  	&sensor_dev_attr_in10_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1499
1500
1501
  	&sensor_dev_attr_in11_input.dev_attr.attr,
  	&sensor_dev_attr_in11_max.dev_attr.attr,
  	&sensor_dev_attr_in11_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1502
  	&sensor_dev_attr_in11_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1503
1504
1505
  	&sensor_dev_attr_in12_input.dev_attr.attr,
  	&sensor_dev_attr_in12_max.dev_attr.attr,
  	&sensor_dev_attr_in12_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1506
  	&sensor_dev_attr_in12_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1507
1508
1509
  	&sensor_dev_attr_in13_input.dev_attr.attr,
  	&sensor_dev_attr_in13_max.dev_attr.attr,
  	&sensor_dev_attr_in13_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1510
  	&sensor_dev_attr_in13_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1511
1512
1513
  	&sensor_dev_attr_in14_input.dev_attr.attr,
  	&sensor_dev_attr_in14_max.dev_attr.attr,
  	&sensor_dev_attr_in14_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1514
  	&sensor_dev_attr_in14_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1515
1516
1517
  	&sensor_dev_attr_in15_input.dev_attr.attr,
  	&sensor_dev_attr_in15_max.dev_attr.attr,
  	&sensor_dev_attr_in15_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1518
  	&sensor_dev_attr_in15_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1519
1520
1521
  	&sensor_dev_attr_in16_input.dev_attr.attr,
  	&sensor_dev_attr_in16_max.dev_attr.attr,
  	&sensor_dev_attr_in16_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1522
  	&sensor_dev_attr_in16_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1523
1524
1525
  	&sensor_dev_attr_fan1_input.dev_attr.attr,
  	&sensor_dev_attr_fan1_div.dev_attr.attr,
  	&sensor_dev_attr_fan1_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1526
  	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1527
1528
1529
  	&sensor_dev_attr_fan2_input.dev_attr.attr,
  	&sensor_dev_attr_fan2_div.dev_attr.attr,
  	&sensor_dev_attr_fan2_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1530
  	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1531
1532
1533
  	&sensor_dev_attr_fan3_input.dev_attr.attr,
  	&sensor_dev_attr_fan3_div.dev_attr.attr,
  	&sensor_dev_attr_fan3_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1534
  	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1535
1536
1537
  	&sensor_dev_attr_fan4_input.dev_attr.attr,
  	&sensor_dev_attr_fan4_div.dev_attr.attr,
  	&sensor_dev_attr_fan4_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1538
  	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1539
1540
1541
  	&sensor_dev_attr_fan5_input.dev_attr.attr,
  	&sensor_dev_attr_fan5_div.dev_attr.attr,
  	&sensor_dev_attr_fan5_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1542
  	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1543
1544
1545
  	&sensor_dev_attr_fan6_input.dev_attr.attr,
  	&sensor_dev_attr_fan6_div.dev_attr.attr,
  	&sensor_dev_attr_fan6_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1546
  	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1547
1548
1549
  	&sensor_dev_attr_fan7_input.dev_attr.attr,
  	&sensor_dev_attr_fan7_div.dev_attr.attr,
  	&sensor_dev_attr_fan7_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1550
  	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1551
1552
1553
  	&sensor_dev_attr_fan8_input.dev_attr.attr,
  	&sensor_dev_attr_fan8_div.dev_attr.attr,
  	&sensor_dev_attr_fan8_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1554
  	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1555
1556
1557
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
  	&sensor_dev_attr_temp1_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1558
  	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1559
1560
1561
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
  	&sensor_dev_attr_temp2_min.dev_attr.attr,
a9273cb8e   Jean Delvare   hwmon: (adm1026) ...
1562
  	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1563
1564
  	&sensor_dev_attr_temp1_offset.dev_attr.attr,
  	&sensor_dev_attr_temp2_offset.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1565
1566
  	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
  	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1567
1568
  	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1569
1570
  	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
  	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1571
1572
  	&sensor_dev_attr_temp1_crit.dev_attr.attr,
  	&sensor_dev_attr_temp2_crit.dev_attr.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1573
1574
  	&dev_attr_temp1_crit_enable.attr,
  	&dev_attr_temp2_crit_enable.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
  	&dev_attr_cpu0_vid.attr,
  	&dev_attr_vrm.attr,
  	&dev_attr_alarms.attr,
  	&dev_attr_alarm_mask.attr,
  	&dev_attr_gpio.attr,
  	&dev_attr_gpio_mask.attr,
  	&dev_attr_pwm1.attr,
  	&dev_attr_pwm2.attr,
  	&dev_attr_pwm3.attr,
  	&dev_attr_pwm1_enable.attr,
  	&dev_attr_pwm2_enable.attr,
  	&dev_attr_pwm3_enable.attr,
  	&dev_attr_temp1_auto_point1_pwm.attr,
  	&dev_attr_temp2_auto_point1_pwm.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1589
1590
  	&dev_attr_temp1_auto_point2_pwm.attr,
  	&dev_attr_temp2_auto_point2_pwm.attr,
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1591
1592
1593
1594
1595
1596
1597
  	&dev_attr_analog_out.attr,
  	NULL
  };
  
  static const struct attribute_group adm1026_group = {
  	.attrs = adm1026_attributes,
  };
5b34dbcd8   Jean Delvare   hwmon: (adm1026) ...
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
  static struct attribute *adm1026_attributes_temp3[] = {
  	&sensor_dev_attr_temp3_input.dev_attr.attr,
  	&sensor_dev_attr_temp3_max.dev_attr.attr,
  	&sensor_dev_attr_temp3_min.dev_attr.attr,
  	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_offset.dev_attr.attr,
  	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
  	&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
  	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
  	&sensor_dev_attr_temp3_crit.dev_attr.attr,
  	&dev_attr_temp3_crit_enable.attr,
  	&dev_attr_temp3_auto_point1_pwm.attr,
  	&dev_attr_temp3_auto_point2_pwm.attr,
1d5f2c16c   Jean Delvare   hwmon: (adm1026) ...
1611
  	NULL
5b34dbcd8   Jean Delvare   hwmon: (adm1026) ...
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
  };
  
  static const struct attribute_group adm1026_group_temp3 = {
  	.attrs = adm1026_attributes_temp3,
  };
  
  static struct attribute *adm1026_attributes_in8_9[] = {
  	&sensor_dev_attr_in8_input.dev_attr.attr,
  	&sensor_dev_attr_in8_max.dev_attr.attr,
  	&sensor_dev_attr_in8_min.dev_attr.attr,
  	&sensor_dev_attr_in8_alarm.dev_attr.attr,
  	&sensor_dev_attr_in9_input.dev_attr.attr,
  	&sensor_dev_attr_in9_max.dev_attr.attr,
  	&sensor_dev_attr_in9_min.dev_attr.attr,
  	&sensor_dev_attr_in9_alarm.dev_attr.attr,
1d5f2c16c   Jean Delvare   hwmon: (adm1026) ...
1627
  	NULL
5b34dbcd8   Jean Delvare   hwmon: (adm1026) ...
1628
1629
1630
1631
1632
  };
  
  static const struct attribute_group adm1026_group_in8_9 = {
  	.attrs = adm1026_attributes_in8_9,
  };
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1633
  /* Return 0 if detection is successful, -ENODEV otherwise */
310ec7921   Jean Delvare   i2c: Drop the kin...
1634
  static int adm1026_detect(struct i2c_client *client,
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1635
  			  struct i2c_board_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
  {
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1637
1638
  	struct i2c_adapter *adapter = client->adapter;
  	int address = client->addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
  	int company, verstep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
1641
1642
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
  		/* We need to be able to do byte I/O */
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1643
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1645
  	/* Now, we do the remaining detection. */
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1646
1647
  	company = adm1026_read_value(client, ADM1026_REG_COMPANY);
  	verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648

57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1649
  	dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
1651
  		" COMPANY: 0x%02x and VERSTEP: 0x%02x
  ",
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1652
  		i2c_adapter_id(client->adapter), client->addr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
  		company, verstep);
52df6440a   Jean Delvare   hwmon: Clean up d...
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
  	/* Determine the chip type. */
  	dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...
  ",
  		i2c_adapter_id(adapter), address);
  	if (company == ADM1026_COMPANY_ANALOG_DEV
  	    && verstep == ADM1026_VERSTEP_ADM1026) {
  		/* Analog Devices ADM1026 */
  	} else if (company == ADM1026_COMPANY_ANALOG_DEV
  		&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
  		dev_err(&adapter->dev, "Unrecognized stepping "
  			"0x%02x. Defaulting to ADM1026.
  ", verstep);
  	} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
  		dev_err(&adapter->dev, "Found version/stepping "
  			"0x%02x. Assuming generic ADM1026.
  ",
  			verstep);
  	} else {
  		dev_dbg(&adapter->dev, "Autodetection failed
  ");
  		/* Not an ADM1026... */
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
  	}
52df6440a   Jean Delvare   hwmon: Clean up d...
1677

57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1678
  	strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679

57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
  	return 0;
  }
  
  static int adm1026_probe(struct i2c_client *client,
  			 const struct i2c_device_id *id)
  {
  	struct adm1026_data *data;
  	int err;
  
  	data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL);
  	if (!data) {
  		err = -ENOMEM;
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694

57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1695
  	i2c_set_clientdata(client, data);
9a61bf630   Ingo Molnar   [PATCH] hwmon: Se...
1696
  	mutex_init(&data->update_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1697

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1698
  	/* Set the VRM version */
303760b44   Jean Delvare   [PATCH] hwmon: hw...
1699
  	data->vrm = vid_which_vrm();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
1701
  
  	/* Initialize the ADM1026 chip */
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1702
  	adm1026_init_client(client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
1704
  
  	/* Register sysfs hooks */
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1705
  	if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1706
  		goto exitfree;
5b34dbcd8   Jean Delvare   hwmon: (adm1026) ...
1707
1708
1709
1710
1711
1712
1713
1714
  	if (data->config1 & CFG1_AIN8_9)
  		err = sysfs_create_group(&client->dev.kobj,
  					 &adm1026_group_in8_9);
  	else
  		err = sysfs_create_group(&client->dev.kobj,
  					 &adm1026_group_temp3);
  	if (err)
  		goto exitremove;
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1715

f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1716
  	data->hwmon_dev = hwmon_device_register(&client->dev);
1beeffe43   Tony Jones   hwmon: Convert fr...
1717
1718
  	if (IS_ERR(data->hwmon_dev)) {
  		err = PTR_ERR(data->hwmon_dev);
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1719
  		goto exitremove;
943b0830c   Mark M. Hoffman   [PATCH] I2C hwmon...
1720
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1721
1722
1723
  	return 0;
  
  	/* Error out and cleanup code */
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1724
  exitremove:
f67fdabfb   Jean Delvare   hwmon: (adm1026) ...
1725
  	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
5b34dbcd8   Jean Delvare   hwmon: (adm1026) ...
1726
1727
1728
1729
  	if (data->config1 & CFG1_AIN8_9)
  		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
  	else
  		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
  exitfree:
1f57ff89f   Alexey Dobriyan   [PATCH] drivers/h...
1731
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
1733
1734
  exit:
  	return err;
  }
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1735

57f7eb0bc   Jean Delvare   hwmon: (adm1026) ...
1736
  static int adm1026_remove(struct i2c_client *client)
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1737
1738
  {
  	struct adm1026_data *data = i2c_get_clientdata(client);
1beeffe43   Tony Jones   hwmon: Convert fr...
1739
  	hwmon_device_unregister(data->hwmon_dev);
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1740
  	sysfs_remove_group(&client->dev.kobj, &adm1026_group);
5b34dbcd8   Jean Delvare   hwmon: (adm1026) ...
1741
1742
1743
1744
  	if (data->config1 & CFG1_AIN8_9)
  		sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
  	else
  		sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
681c6f7a6   Mark M. Hoffman   hwmon: Fix unchec...
1745
1746
1747
  	kfree(data);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748
1749
1750
1751
  static int __init sm_adm1026_init(void)
  {
  	return i2c_add_driver(&adm1026_driver);
  }
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1752
  static void __exit sm_adm1026_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1753
1754
1755
1756
1757
1758
  {
  	i2c_del_driver(&adm1026_driver);
  }
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
cb01a2312   Jean Delvare   hwmon: (adm1026) ...
1759
  	      "Justin Thiessen <jthiessen@penguincomputing.com>");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
1761
1762
1763
  MODULE_DESCRIPTION("ADM1026 driver");
  
  module_init(sm_adm1026_init);
  module_exit(sm_adm1026_exit);