Changeset 2453
- Timestamp:
- 04/19/04 21:46:14 (5 years ago)
- Files:
-
- lm-sensors/trunk/doc/chips/SUMMARY (modified) (1 diff)
- lm-sensors/trunk/doc/chips/pc87360 (modified) (3 diffs)
- lm-sensors/trunk/kernel/chips/pc87360.c (modified) (27 diffs)
- lm-sensors/trunk/lib/chips.c (modified) (4 diffs)
- lm-sensors/trunk/lib/chips.h (modified) (1 diff)
- lm-sensors/trunk/prog/sensors/chips.c (modified) (3 diffs)
- lm-sensors/trunk/prog/sensors/chips.h (modified) (1 diff)
- lm-sensors/trunk/prog/sensors/main.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
lm-sensors/trunk/doc/chips/SUMMARY
r2444 r2453 159 159 pc87363 - - 2 2 pwm no yes (LPC) 160 160 pc87364 - - 3 3 pwm no yes (LPC) 161 pc87365 - -3 3 pwm no yes (LPC)162 pc87366 - -3 3 pwm no yes (LPC)161 pc87365 2 11 3 3 pwm no yes (LPC) 162 pc87366 3 11 3 3 pwm no yes (LPC) 163 163 164 164 sis5595 lm-sensors/trunk/doc/chips/pc87360
r2427 r2453 33 33 hardware monitoring chipsets, not only controling and monitoring three fans, 34 34 but also monitoring eleven voltage inputs and two (PC87365) or three 35 (PC87366) remote temperatures. For now, the driver doesn't handle these 36 features and treat these two chips as PC87364. 35 (PC87366) remote temperatures. 37 36 38 37 Fan rotation speeds are reported in RPM (revolutions per minute). An alarm … … 48 47 PWM values are from 0 to 255. 49 48 49 Temperatures are reported in degrees Celcius. Each temperature measured has 50 associated low limit, high limit and overtemperature limit, each of which 51 triggers an alarm when crossed. 52 53 Voltages are reported relatively to a relative voltage, either internal or 54 external. Some of them are divided by two internally, you will have to 55 compensate in sensors.conf. Each voltage measured has associated low and 56 high limit, each of which triggers an alarm when crossed. 57 50 58 If an alarm triggers, it will remain triggered until the hardware register 51 59 is read at least once. This means that the cause for the alarm may … … 59 67 ----------- 60 68 61 Th is driver only supports fansat the moment.69 The voltages and temperatures are read-only at the moment. 62 70 63 71 The datasheets suggests that some values (fan mins, fan divisors) lm-sensors/trunk/kernel/chips/pc87360.c
r2445 r2453 45 45 static unsigned int normal_isa_range[] = { SENSORS_ISA_END }; 46 46 static u8 devid; 47 static unsigned int extra_isa[] = { 0x0000, 0x0000, 0x0000 }; 47 48 48 49 SENSORS_INSMOD_5(pc87360, pc87363, pc87364, pc87365, pc87366); 49 50 50 /* modified from kernel/include/traps.c */ 51 /* 52 * Super-I/O registers and operations 53 */ 54 51 55 #define REG 0x2e /* The register to read/write */ 56 #define VAL 0x2f /* The value to read/write */ 57 52 58 #define DEV 0x07 /* Register: Logical device select */ 53 #define VAL 0x2f /* The value to read/write */54 #define FSCM 0x09 /* The device with the fan registers in it */55 59 #define DEVID 0x20 /* Register: Device ID */ 60 #define ACT 0x30 /* Register: Device activation */ 61 #define BASE 0x60 /* Register: Base address */ 62 63 #define FSCM 0x09 /* Logical device: fans */ 64 #define VLM 0x0d /* Logical device: voltages */ 65 #define TMS 0x0e /* Logical device: temperatures */ 66 static const u8 logdev[3] = { FSCM, VLM, TMS }; 56 67 57 68 static inline void superio_outb(int reg, int val) … … 67 78 } 68 79 69 static inline void superio_select(void)70 {71 outb(DEV, REG);72 outb(FSCM, VAL);73 }74 75 80 static inline void superio_exit(void) 76 81 { … … 79 84 } 80 85 86 #define PC87360_EXTENT 0x10 87 81 88 /* 82 * The PC87360 (device id 0xE1) and PC87363 (device id 0xE8) monitor and 83 * control two fans. 84 * The PC87364 (device id 0xE4), PC87365 (device id 0xE5) and PC87366 85 * (device id 0xE9) monitor and control three fans. 89 * Fan registers and conversions 86 90 */ 87 #define PC87360_DEVID_MATCH(id) ((id) == 0xE1 || (id) == 0xE8 || \88 (id) == 0xE4 || (id) == 0xE5 || \89 (id) == 0xE9)90 91 #define PC87360_BASE_REG 0x6092 #define PC87360_ACTIVATE_REG 0x3093 94 #define PC87360_EXTENT 0x1095 91 96 92 /* nr has to be 0 or 1 (PC87360/87363) or 2 (PC87364/87365/87366) */ … … 101 97 #define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr)) 102 98 103 #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0: \ 104 960000/((val)*(div))) 105 #define FAN_TO_REG(val,div) ((val)<=0?255: \ 106 960000/((val)*(div))) 107 #define FAN_DIV_FROM_REG(val) (1 << ((val >> 5) & 0x03)) 108 #define FAN_DIV_TO_REG(val) ((val)==8?0x60:(val)==4?0x40:(val)==1?0x00:0x20) 109 #define ALARM_FROM_REG(val) ((val) & 0x07) 99 #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0: \ 100 960000/((val)*(div))) 101 #define FAN_TO_REG(val,div) ((val)<=0?255: \ 102 960000/((val)*(div))) 103 #define FAN_DIV_FROM_REG(val) (1 << ((val >> 5) & 0x03)) 104 #define FAN_DIV_TO_REG(val) ((val)==8?0x60:(val)==4?0x40:(val)==1?0x00:0x20) 105 #define FAN_STATUS_FROM_REG(val) ((val) & 0x07) 106 107 /* 108 * Voltage registers and conversions 109 */ 110 111 #define PC87365_REG_IN_BANK 0x09 112 113 /* nr has to be 0 to 11 (PC87365/87366) */ 114 #define PC87365_REG_IN 0x0B 115 #define PC87365_REG_IN_MIN 0x0D 116 #define PC87365_REG_IN_MAX 0x0C 117 #define PC87365_REG_IN_STATUS 0x0A 118 #define PC87365_REG_IN_ALARMS1 0x00 119 #define PC87365_REG_IN_ALARMS2 0x01 120 121 #define IN_FROM_REG(val) (((val) * 2967 + 127) / 255) 122 #define IN_STATUS_FROM_REG(val) ((val) & 0x86) 123 124 /* 125 * Temperature registers and conversions 126 */ 127 128 #define PC87365_REG_TEMP_BANK 0x09 129 130 /* nr has to be 0 to 1 (PC87365) or 2 (PC87366) */ 131 #define PC87365_REG_TEMP 0x0B 132 #define PC87365_REG_TEMP_MIN 0x0D 133 #define PC87365_REG_TEMP_MAX 0x0C 134 #define PC87365_REG_TEMP_CRIT 0x0D 135 #define PC87365_REG_TEMP_STATUS 0x0A 136 #define PC87365_REG_TEMP_ALARMS 0x00 137 138 #define TEMP_FROM_REG(val) ((val)&0x80 ? (val) : (val) - 128) 139 #define TEMP_STATUS_FROM_REG(val) ((val) & 0xCE) 110 140 111 141 struct pc87360_data { … … 113 143 struct semaphore lock; 114 144 int sysctl_id; 145 int address[3]; 115 146 116 147 struct semaphore update_lock; … … 118 149 unsigned long last_updated; /* In jiffies */ 119 150 120 u8 fannr ;151 u8 fannr, innr, tempnr; 121 152 122 153 u8 fan[3]; /* Register value */ … … 124 155 u8 fan_status[3]; /* Register value */ 125 156 u8 pwm[3]; /* Register value */ 157 158 u8 in[11]; /* Register value */ 159 u8 in_min[11]; /* Register value */ 160 u8 in_max[11]; /* Register value */ 161 u8 in_status[11]; /* Register value */ 162 u16 in_alarms; /* Register values, combined */ 163 164 u8 temp[3]; /* Register value */ 165 u8 temp_min[3]; /* Register value */ 166 u8 temp_max[3]; /* Register value */ 167 u8 temp_crit[3]; /* Register value */ 168 u8 temp_status[3]; /* Register value */ 169 u8 temp_alarms; /* Register value */ 126 170 }; 127 171 … … 132 176 static int pc87360_detach_client(struct i2c_client *client); 133 177 134 static int pc87360_read_value(struct i2c_client *client, u8 register);135 static int pc87360_write_value(struct i2c_client *client, u8 register,178 static int pc87360_read_value(struct pc87360_data *data, int ldi, u8 reg); 179 static int pc87360_write_value(struct pc87360_data *data, int ldi, u8 reg, 136 180 u8 value); 137 181 static void pc87360_update_client(struct i2c_client *client); 138 static void pc87360_init_client(struct i2c_client *client); 139 static int pc87360_find(int *address, u8 *devid); 140 182 static int pc87360_find(u8 *devid, int *address); 183 184 185 void pc87365_alarms(struct i2c_client *client, int operation, int ctl_name, 186 int *nrels_mag, long *results); 141 187 142 188 static void pc87360_fan(struct i2c_client *client, int operation, … … 149 195 int ctl_name, int *nrels_mag, long *results); 150 196 197 void pc87365_in(struct i2c_client *client, int operation, int ctl_name, 198 int *nrels_mag, long *results); 199 void pc87365_in_status(struct i2c_client *client, int operation, int ctl_name, 200 int *nrels_mag, long *results); 201 202 void pc87365_temp(struct i2c_client *client, int operation, int ctl_name, 203 int *nrels_mag, long *results); 204 void pc87365_temp_status(struct i2c_client *client, int operation, int ctl_name, 205 int *nrels_mag, long *results); 206 151 207 static int pc87360_id = 0; 152 208 … … 160 216 161 217 /* -- SENSORS SYSCTL START -- */ 218 219 #define PC87365_SYSCTL_ALARMS 100 /* bit field */ 162 220 163 221 #define PC87360_SYSCTL_FAN1 1101 /* Rotations/min */ … … 172 230 #define PC87360_SYSCTL_PWM3 1403 /* not for PC87360/PC87363 */ 173 231 174 #define PC87360_ALARM_FAN_READY 0x01 175 #define PC87360_ALARM_FAN_LOW 0x02 176 #define PC87360_ALARM_FAN_OVERFLOW 0x04 232 #define PC87360_STATUS_FAN_READY 0x01 233 #define PC87360_STATUS_FAN_LOW 0x02 234 #define PC87360_STATUS_FAN_OVERFLOW 0x04 235 236 #define PC87365_SYSCTL_IN0 2100 /* mV */ 237 #define PC87365_SYSCTL_IN1 2101 238 #define PC87365_SYSCTL_IN2 2102 239 #define PC87365_SYSCTL_IN3 2103 240 #define PC87365_SYSCTL_IN4 2104 241 #define PC87365_SYSCTL_IN5 2105 242 #define PC87365_SYSCTL_IN6 2106 243 #define PC87365_SYSCTL_IN7 2107 244 #define PC87365_SYSCTL_IN8 2108 245 #define PC87365_SYSCTL_IN9 2109 246 #define PC87365_SYSCTL_IN10 2110 247 #define PC87365_SYSCTL_IN0_STATUS 2300 /* bit field */ 248 #define PC87365_SYSCTL_IN1_STATUS 2301 249 #define PC87365_SYSCTL_IN2_STATUS 2302 250 #define PC87365_SYSCTL_IN3_STATUS 2303 251 #define PC87365_SYSCTL_IN4_STATUS 2304 252 #define PC87365_SYSCTL_IN5_STATUS 2305 253 #define PC87365_SYSCTL_IN6_STATUS 2306 254 #define PC87365_SYSCTL_IN7_STATUS 2307 255 #define PC87365_SYSCTL_IN8_STATUS 2308 256 #define PC87365_SYSCTL_IN9_STATUS 2309 257 #define PC87365_SYSCTL_IN10_STATUS 2310 258 259 #define PC87365_STATUS_IN_MIN 0x02 260 #define PC87365_STATUS_IN_MAX 0x04 261 262 #define PC87365_SYSCTL_TEMP1 3101 /* degrees Celcius */ 263 #define PC87365_SYSCTL_TEMP2 3102 264 #define PC87365_SYSCTL_TEMP3 3103 /* not for PC87365 */ 265 #define PC87365_SYSCTL_TEMP1_STATUS 3101 /* bit field */ 266 #define PC87365_SYSCTL_TEMP2_STATUS 3102 267 #define PC87365_SYSCTL_TEMP3_STATUS 3103 /* not for PC87365 */ 268 269 #define PC87365_STATUS_TEMP_MIN 0x02 270 #define PC87365_STATUS_TEMP_MAX 0x04 271 #define PC87365_STATUS_TEMP_CRIT 0x08 272 #define PC87365_STATUS_TEMP_OPEN 0x40 177 273 178 274 /* -- SENSORS SYSCTL END -- */ 179 275 180 static ctl_table pc87360_dir_table_template[] = { /* PC87363 too */ 181 {PC87360_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, 182 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan}, 183 {PC87360_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, 184 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan}, 185 {PC87360_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, 186 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_div}, 187 {PC87360_SYSCTL_FAN1_STATUS, "fan1_status", NULL, 0, 0444, NULL, 188 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status}, 189 {PC87360_SYSCTL_FAN2_STATUS, "fan2_status", NULL, 0, 0444, NULL, 190 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status}, 191 {PC87360_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, 192 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm}, 193 {PC87360_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, 194 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm}, 195 {0} 196 }; 197 198 static ctl_table pc87364_dir_table_template[] = { /* PC87365 and PC87366 too */ 276 static ctl_table pc87360_dir_table_template[] = { /* PC87363 and PC87364 too */ 199 277 {PC87360_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, 200 278 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan}, … … 220 298 }; 221 299 300 static ctl_table pc87365_dir_table_template[] = { /* PC87366 too */ 301 {PC87365_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, 302 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_alarms}, 303 {PC87360_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, 304 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan}, 305 {PC87360_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, 306 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan}, 307 {PC87360_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL, 308 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan}, 309 {PC87360_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL, 310 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_div}, 311 {PC87360_SYSCTL_FAN1_STATUS, "fan1_status", NULL, 0, 0444, NULL, 312 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status}, 313 {PC87360_SYSCTL_FAN2_STATUS, "fan2_status", NULL, 0, 0444, NULL, 314 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status}, 315 {PC87360_SYSCTL_FAN3_STATUS, "fan3_status", NULL, 0, 0444, NULL, 316 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_fan_status}, 317 {PC87360_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL, 318 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm}, 319 {PC87360_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL, 320 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm}, 321 {PC87360_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL, 322 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87360_pwm}, 323 {PC87365_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, 324 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 325 {PC87365_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, 326 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 327 {PC87365_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, 328 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 329 {PC87365_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, 330 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 331 {PC87365_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, 332 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 333 {PC87365_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, 334 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 335 {PC87365_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL, 336 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 337 {PC87365_SYSCTL_IN7, "in7", NULL, 0, 0644, NULL, 338 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 339 {PC87365_SYSCTL_IN8, "in8", NULL, 0, 0644, NULL, 340 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 341 {PC87365_SYSCTL_IN9, "in9", NULL, 0, 0644, NULL, 342 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 343 {PC87365_SYSCTL_IN10, "in10", NULL, 0, 0644, NULL, 344 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in}, 345 {PC87365_SYSCTL_IN0_STATUS, "in0_status", NULL, 0, 0444, NULL, 346 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 347 {PC87365_SYSCTL_IN1_STATUS, "in1_status", NULL, 0, 0444, NULL, 348 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 349 {PC87365_SYSCTL_IN2_STATUS, "in2_status", NULL, 0, 0444, NULL, 350 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 351 {PC87365_SYSCTL_IN3_STATUS, "in3_status", NULL, 0, 0444, NULL, 352 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 353 {PC87365_SYSCTL_IN4_STATUS, "in4_status", NULL, 0, 0444, NULL, 354 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 355 {PC87365_SYSCTL_IN5_STATUS, "in5_status", NULL, 0, 0444, NULL, 356 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 357 {PC87365_SYSCTL_IN6_STATUS, "in6_status", NULL, 0, 0444, NULL, 358 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 359 {PC87365_SYSCTL_IN7_STATUS, "in7_status", NULL, 0, 0444, NULL, 360 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 361 {PC87365_SYSCTL_IN8_STATUS, "in8_status", NULL, 0, 0444, NULL, 362 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 363 {PC87365_SYSCTL_IN9_STATUS, "in9_status", NULL, 0, 0444, NULL, 364 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 365 {PC87365_SYSCTL_IN10_STATUS, "in10_status", NULL, 0, 0444, NULL, 366 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_in_status}, 367 {PC87365_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL, 368 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp}, 369 {PC87365_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL, 370 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp}, 371 {PC87365_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL, 372 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp}, 373 {PC87365_SYSCTL_TEMP1_STATUS, "temp1_status", NULL, 0, 0644, NULL, 374 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp_status}, 375 {PC87365_SYSCTL_TEMP2_STATUS, "temp2_status", NULL, 0, 0644, NULL, 376 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp_status}, 377 {PC87365_SYSCTL_TEMP3_STATUS, "temp3_status", NULL, 0, 0644, NULL, 378 &i2c_proc_real, &i2c_sysctl_real, NULL, &pc87365_temp_status}, 379 {0} 380 }; 381 222 382 static int pc87360_attach_adapter(struct i2c_adapter *adapter) 223 383 { … … 225 385 } 226 386 227 static int pc87360_find( int *address, u8 *devid)387 static int pc87360_find(u8 *devid, int *address) 228 388 { 229 389 u16 val; 390 int i; 391 int nrdev; /* logical device count */ 230 392 231 393 /* no superio_enter */ 394 395 /* identify device */ 232 396 val = superio_inb(DEVID); 233 if (!PC87360_DEVID_MATCH(val)) { 397 switch (val) { 398 case 0xE1: /* PC87360 */ 399 case 0xE8: /* PC87363 */ 400 case 0xE4: /* PC87364 */ 401 nrdev = 1; 402 break; 403 case 0xE5: /* PC87365 */ 404 case 0xE9: /* PC87366 */ 405 nrdev = 3; 406 break; 407 default: 234 408 superio_exit(); 235 409 return -ENODEV; 236 410 } 411 /* remember the device id */ 237 412 *devid = val; 238 413 239 superio_select(); 240 241 val = superio_inb(PC87360_ACTIVATE_REG); 242 if (!(val & 0x01)) { 243 printk("pc87360.o: device not activated\n"); 244 superio_exit(); 245 return -ENODEV; 246 } 247 248 val = (superio_inb(PC87360_BASE_REG) << 8) 249 | superio_inb(PC87360_BASE_REG + 1); 250 *address = val & ~(PC87360_EXTENT - 1); 251 if (*address == 0) { 252 printk("pc87360.o: base address not set\n"); 253 superio_exit(); 254 return -ENODEV; 414 for (i = 0; i < nrdev; i++) { 415 /* select logical device */ 416 superio_outb(DEV, logdev[i]); 417 418 val = superio_inb(ACT); 419 if (!(val & 0x01)) { 420 printk(KERN_INFO "pc87360.o: device 0x%02x not " 421 "activated\n", logdev[i]); 422 continue; 423 } 424 425 val = (superio_inb(BASE) << 8) 426 | superio_inb(BASE + 1); 427 if (!val) { 428 printk(KERN_INFO "pc87360.o: base address not set for " 429 "device 0x%02x\n", logdev[i]); 430 continue; 431 } 432 433 address[i] = val; 255 434 } 256 435 … … 259 438 } 260 439 440 /* We should not trust the address, it is unset. 441 Read from extra_isa instead. */ 261 442 int pc87360_detect(struct i2c_adapter *adapter, int address, 262 443 unsigned short flags, int kind) … … 273 454 } 274 455 275 if (check_region(address, PC87360_EXTENT)) { 276 printk("pc87360.o: region 0x%x already in use!\n", address); 277 return -ENODEV; 456 for (i = 0; i < 3; i++) { 457 if (extra_isa[i] && check_region(extra_isa[i], PC87360_EXTENT)) { 458 printk("pc87360.o: region 0x%x already in use!\n", address); 459 return -ENODEV; 460 } 278 461 } 279 462 … … 291 474 292 475 data->fannr = 2; 293 476 data->innr = 0; 477 data->tempnr = 0; 478 294 479 switch (devid) { 295 case 0xe8: 296 type_name = "pc87363"; 297 break; 298 case 0xe4: 299 type_name = "pc87364"; 300 data->fannr = 3; 301 break; 302 case 0xe5: 303 type_name = "pc87365"; 304 data->fannr = 3; 305 break; 306 case 0xe9: 307 type_name = "pc87366"; 308 data->fannr = 3; 309 break; 310 } 311 312 request_region(address, PC87360_EXTENT, "pc87360"); 480 case 0xe8: 481 type_name = "pc87363"; 482 break; 483 case 0xe4: 484 type_name = "pc87364"; 485 data->fannr = 3; 486 break; 487 case 0xe5: 488 type_name = "pc87365"; 489 data->fannr = 3; 490 data->innr = 11; 491 data->tempnr = 2; 492 break; 493 case 0xe9: 494 type_name = "pc87366"; 495 data->fannr = 3; 496 data->innr = 11; 497 data->tempnr = 3; 498 break; 499 } 500 501 for (i = 0; i < 3; i++) { 502 if ((data->address[i] = extra_isa[i])) { 503 request_region(extra_isa[i], PC87360_EXTENT, "pc87360"); 504 } 505 } 313 506 strcpy(new_client->name, client_name); 314 507 … … 321 514 322 515 if ((i = i2c_register_entry((struct i2c_client *) new_client, 323 type_name, 324 (data->fannr == 3) ? 325 pc87364_dir_table_template : 516 type_name, data->innr ? 517 pc87365_dir_table_template : 326 518 pc87360_dir_table_template)) < 0) { 327 519 err = i; … … 330 522 data->sysctl_id = i; 331 523 332 pc87360_init_client(new_client);333 524 return 0; 334 525 … … 343 534 static int pc87360_detach_client(struct i2c_client *client) 344 535 { 345 int err; 346 347 i2c_deregister_entry(((struct pc87360_data *) (client->data))->sysctl_id); 536 struct pc87360_data *data = client->data; 537 int i, err; 538 539 i2c_deregister_entry(data->sysctl_id); 348 540 349 541 if ((err = i2c_detach_client(client))) { … … 353 545 } 354 546 355 release_region(client->addr, PC87360_EXTENT); 547 for (i = 0; i < 3; i++) { 548 if (data->address[i]) { 549 release_region(data->address[i], PC87360_EXTENT); 550 } 551 } 356 552 kfree(client->data); 357 553 … … 359 555 } 360 556 361 static int pc87360_read_value(struct i2c_client *client, u8 reg) 557 /* ldi is the logical device index: 558 0: fans 559 1: voltages 560 2: temperatures */ 561 static int pc87360_read_value(struct pc87360_data *data, int ldi, u8 reg) 362 562 { 363 563 int res; 364 564 365 res = inb_p(client->addr + reg); 565 down(&(data->lock)); 566 res = inb_p(data->address[ldi] + reg); 567 up(&(data->lock)); 366 568 return res; 367 569 } 368 570 369 static int pc87360_write_value(struct i2c_client *client, u8 reg, u8 value) 370 { 371 outb_p(value, client->addr + reg); 571 static int pc87360_write_value(struct pc87360_data *data, int ldi, u8 reg, 572 u8 value) 573 { 574 down(&(data->lock)); 575 outb_p(value, data->address[ldi] + reg); 576 up(&(data->lock)); 372 577 return 0; 373 }374 375 static void pc87360_init_client(struct i2c_client *client)376 {377 /* nothing yet, read only driver */378 578 } 379 579 … … 388 588 (jiffies < data->last_updated) || !data->valid) { 389 589 for (i = 0; i < data->fannr; i++) { 390 data->fan[i] = pc87360_read_value(client, PC87360_REG_FAN(i)); 391 data->fan_min[i] = pc87360_read_value(client, PC87360_REG_FAN_MIN(i)); 392 data->fan_status[i] = pc87360_read_value(client, PC87360_REG_FAN_STATUS(i)); 393 data->pwm[i] = pc87360_read_value(client, PC87360_REG_PWM(i)); 590 data->fan[i] = pc87360_read_value(data, 0, PC87360_REG_FAN(i)); 591 data->fan_min[i] = pc87360_read_value(data, 0, PC87360_REG_FAN_MIN(i)); 592 data->fan_status[i] = pc87360_read_value(data, 0, PC87360_REG_FAN_STATUS(i)); 593 data->pwm[i] = pc87360_read_value(data, 0, PC87360_REG_PWM(i)); 594 } 595 596 for (i = 0; i < data->innr; i++) { 597 pc87360_write_value(data, 1, PC87365_REG_IN_BANK, i); 598 data->in_status[i] = pc87360_read_value(data, 1, PC87365_REG_IN_STATUS); 599 if (data->in_status[i] & 0x01) { 600 data->in[i] = pc87360_read_value(data, 1, PC87365_REG_IN); 601 data->in_min[i] = pc87360_read_value(data, 1, PC87365_REG_IN_MIN); 602 data->in_max[i] = pc87360_read_value(data, 1, PC87365_REG_IN_MAX); 603 } 604 data->in_alarms = pc87360_read_value(data, 1, PC87365_REG_IN_ALARMS1) 605 | (pc87360_read_value(data, 1, PC87365_REG_IN_ALARMS2) << 8); 606 } 607 608 for (i = 0; i < data->tempnr; i++) { 609 pc87360_write_value(data, 2, PC87365_REG_TEMP_BANK, i); 610 data->temp_status[i] = pc87360_read_value(data, 2, PC87365_REG_TEMP_STATUS); 611 if (data->temp_status[i] & 0x01) { 612 data->temp[i] = pc87360_read_value(data, 2, PC87365_REG_TEMP); 613 data->temp_min[i] = pc87360_read_value(data, 2, PC87365_REG_TEMP_MIN); 614 data->temp_max[i] = pc87360_read_value(data, 2, PC87365_REG_TEMP_MAX); 615 data->temp_crit[i] = pc87360_read_value(data, 2, PC87365_REG_TEMP_CRIT); 616 } 617 data->temp_alarms = pc87360_read_value(data, 2, PC87365_REG_TEMP_ALARMS); 394 618 } 395 619 … … 401 625 } 402 626 627 628 void pc87365_alarms(struct i2c_client *client, int operation, int ctl_name, 629 int *nrels_mag, long *results) 630 { 631 struct pc87360_data *data = client->data; 632 633 if (operation == SENSORS_PROC_REAL_INFO) 634 *nrels_mag = 0; 635 else if (operation == SENSORS_PROC_REAL_READ) { 636 pc87360_update_client(client); 637 results[0] = data->in_alarms; 638 results[1] = data->temp_alarms; 639 *nrels_mag = 2; 640 } 641 } 403 642 404 643 void pc87360_fan(struct i2c_client *client, int operation, int ctl_name, … … 423 662 data->fan_min[nr] = FAN_TO_REG(results[0], 424 663 FAN_DIV_FROM_REG(data->fan_status[nr])); 425 pc87360_write_value( client, PC87360_REG_FAN_MIN(nr),664 pc87360_write_value(data, 0, PC87360_REG_FAN_MIN(nr), 426 665 data->fan_min[nr]); 427 666 } … … 452 691 data->fan_status[i] = (data->fan_status[i] & 0x9F) 453 692 | FAN_DIV_TO_REG(results[i]); 454 pc87360_write_value( client, PC87360_REG_FAN_STATUS(i),693 pc87360_write_value(data, 0, PC87360_REG_FAN_STATUS(i), 455 694 data->fan_status[i]); 456 695 data->fan_min[i] = FAN_TO_REG(fan_min, 457 696 FAN_DIV_FROM_REG(data->fan_status[i])); 458 pc87360_write_value( client, PC87360_REG_FAN_MIN(i),697 pc87360_write_value(data, 0, PC87360_REG_FAN_MIN(i), 459 698 data->fan_min[i]); 460 699 } … … 479 718 { 480 719 data->pwm[nr] = SENSORS_LIMIT(results[0], 0, 255); 481 pc87360_write_value( client, PC87360_REG_PWM(nr),720 pc87360_write_value(data, 0, PC87360_REG_PWM(nr), 482 721 data->pwm[nr]); 483 722 } … … 495 734 else if (operation == SENSORS_PROC_REAL_READ) { 496 735 pc87360_update_client(client); 497 results[0] = ALARM_FROM_REG(data->pwm[nr]);736 results[0] = FAN_STATUS_FROM_REG(data->fan_status[nr]); 498 737 *nrels_mag = 1; 499 738 } 500 739 } 501 740 741 void pc87365_in(struct i2c_client *client, int operation, int ctl_name, 742 int *nrels_mag, long *results) 743 { 744 struct pc87360_data *data = client->data; 745 int nr = ctl_name - PC87365_SYSCTL_IN0; 746 747 if (operation == SENSORS_PROC_REAL_INFO) 748 *nrels_mag = 3; 749 else if (operation == SENSORS_PROC_REAL_READ) { 750 pc87360_update_client(client); 751 results[0] = IN_FROM_REG(data->in_max[nr]); 752 results[1] = IN_FROM_REG(data->in_min[nr]); 753 results[2] = IN_FROM_REG(data->in[nr]); 754 *nrels_mag = 3; 755 } 756 } 757 758 void pc87365_in_status(struct i2c_client *client, int operation, int ctl_name, 759 int *nrels_mag, long *results) 760 { 761 struct pc87360_data *data = client->data; 762 int nr = ctl_name - PC87365_SYSCTL_IN0_STATUS; 763 764 if (operation == SENSORS_PROC_REAL_INFO) 765 *nrels_mag = 0; 766 else if (operation == SENSORS_PROC_REAL_READ) { 767 pc87360_update_client(client); 768 results[0] = IN_STATUS_FROM_REG(data->in_status[nr]); 769 *nrels_mag = 1; 770 } 771 } 772 773 void pc87365_temp(struct i2c_client *client, int operation, int ctl_name, 774 int *nrels_mag, long *results) 775 { 776 struct pc87360_data *data = client->data; 777 int nr = ctl_name - PC87365_SYSCTL_TEMP1; 778 779 if (operation == SENSORS_PROC_REAL_INFO) 780 *nrels_mag = 0; 781 else if (operation == SENSORS_PROC_REAL_READ) { 782 pc87360_update_client(client); 783 results[0] = TEMP_FROM_REG(data->temp_max[nr]); 784 results[1] = TEMP_FROM_REG(data->temp_min[nr]); 785 results[1] = TEMP_FROM_REG(data->temp_crit[nr]); 786 results[2] = TEMP_FROM_REG(data->temp[nr]); 787 *nrels_mag = 4; 788 } 789 } 790 791 void pc87365_temp_status(struct i2c_client *client, int operation, int ctl_name, 792 int *nrels_mag, long *results) 793 { 794 struct pc87360_data *data = client->data; 795 int nr = ctl_name - PC87365_SYSCTL_TEMP1_STATUS; 796 797 if (operation == SENSORS_PROC_REAL_INFO) 798 *nrels_mag = 0; 799 else if (operation == SENSORS_PROC_REAL_READ) { 800 pc87360_update_client(client); 801 results[0] = TEMP_STATUS_FROM_REG(data->temp_status[nr]); 802 *nrels_mag = 1; 803 } 804 } 805 806 502 807 static int __init pc87360_init(void) 503 808 { 504 int addr;505 506 809 printk("pc87360.o version %s (%s)\n", LM_VERSION, LM_DATE); 507 810 508 if (pc87360_find(& addr, &devid)) {811 if (pc87360_find(&devid, extra_isa)) { 509 812 printk("pc87360.o: PC8736x not detected, module not inserted.\n"); 510 813 return -ENODEV; 511 814 } 512 normal_isa[0] = addr;513 815 514 816 return i2c_add_driver(&pc87360_driver); lm-sensors/trunk/lib/chips.c
r2427 r2453 4258 4258 { SENSORS_PC87360_FAN2, "fan2", NOMAP, NOMAP, R, 4259 4259 PC87360_SYSCTL_FAN2, VALUE(2), 0 }, 4260 { SENSORS_PC87360_FAN3, "fan3", NOMAP, NOMAP, R, 4261 PC87360_SYSCTL_FAN3, VALUE(2), 0 }, 4260 4262 { SENSORS_PC87360_FAN1_MIN, "fan1_min", SENSORS_PC87360_FAN1, 4261 4263 SENSORS_PC87360_FAN1, RW, PC87360_SYSCTL_FAN1, … … 4264 4266 SENSORS_PC87360_FAN2, RW, PC87360_SYSCTL_FAN2, 4265 4267 VALUE(1), 0 }, 4268 { SENSORS_PC87360_FAN3_MIN, "fan3_min", SENSORS_PC87360_FAN3, 4269 SENSORS_PC87360_FAN3, RW, PC87360_SYSCTL_FAN3, 4270 VALUE(1), 0 }, 4266 4271 { SENSORS_PC87360_FAN1_DIV, "fan1_div", SENSORS_PC87360_FAN1, 4267 4272 NOMAP, RW, PC87360_SYSCTL_FAN_DIV, VALUE(1), 0 }, 4268 4273 { SENSORS_PC87360_FAN2_DIV, "fan2_div", SENSORS_PC87360_FAN2, 4269 4274 NOMAP, RW, PC87360_SYSCTL_FAN_DIV, VALUE(2), 0 }, 4275 { SENSORS_PC87360_FAN3_DIV, "fan3_div", SENSORS_PC87360_FAN3, 4276 NOMAP, RW, PC87360_SYSCTL_FAN_DIV, VALUE(3), 0 }, 4270 4277 { SENSORS_PC87360_FAN1_STATUS, "fan1_status", SENSORS_PC87360_FAN1, 4271 4278 NOMAP, R, PC87360_SYSCTL_FAN1_STATUS, VALUE(1), 0 }, 4272 4279 { SENSORS_PC87360_FAN2_STATUS, "fan2_status", SENSORS_PC87360_FAN2, 4273 4280 NOMAP, R, PC87360_SYSCTL_FAN2_STATUS, VALUE(1), 0 }, 4281 { SENSORS_PC87360_FAN3_STATUS, "fan3_status", SENSORS_PC87360_FAN3, 4282 NOMAP, R, PC87360_SYSCTL_FAN3_STATUS, VALUE(1), 0 }, 4274 4283 { 0 } 4275 4284 }; 4276 4285 4277 static sensors_chip_feature pc8736 4_features[] =4286 static sensors_chip_feature pc87365_features[] = 4278 4287 { 4288 { SENSORS_PC87360_ALARMS_IN, "alarms_in", NOMAP, NOMAP, R, 4289 PC87365_SYSCTL_ALARMS, VALUE(1), 0 }, 4290 { SENSORS_PC87360_ALARMS_TEMP, "alarms_temp", NOMAP, NOMAP, R, 4291 PC87365_SYSCTL_ALARMS, VALUE(2), 0 }, 4279 4292 { SENSORS_PC87360_FAN1, "fan1", NOMAP, NOMAP, R, 4280 4293 PC87360_SYSCTL_FAN1, VALUE(2), 0 }, … … 4304 4317 { SENSORS_PC87360_FAN3_STATUS, "fan3_status", SENSORS_PC87360_FAN3, 4305 4318 NOMAP, R, PC87360_SYSCTL_FAN3_STATUS, VALUE(1), 0 }, 4319 { SENSORS_PC87360_IN0, "in0", NOMAP, NOMAP, R, 4320 PC87365_SYSCTL_IN0, VALUE(3), 2 }, 4321 { SENSORS_PC87360_IN1, "in1", NOMAP, NOMAP, R, 4322 PC87365_SYSCTL_IN1, VALUE(3), 2 }, 4323 { SENSORS_PC87360_IN2, "in2", NOMAP, NOMAP, R, 4324 PC87365_SYSCTL_IN2, VALUE(3), 2 }, 4325 { SENSORS_PC87360_IN3, "in3", NOMAP, NOMAP, R, 4326 PC87365_SYSCTL_IN3, VALUE(3), 2 }, 4327 { SENSORS_PC87360_IN4, "in4", NOMAP, NOMAP, R, 4328 PC87365_SYSCTL_IN4, VALUE(3), 2 }, 4329 { SENSORS_PC87360_IN5, "in5", NOMAP, NOMAP, R, 4330 PC87365_SYSCTL_IN5, VALUE(3), 2 }, 4331 { SENSORS_PC87360_IN6, "in6", NOMAP, NOMAP, R, 4332 PC87365_SYSCTL_IN6, VALUE(3), 2 }, 4333 { SENSORS_PC87360_IN7, "in7", NOMAP, NOMAP, R, 4334 PC87365_SYSCTL_IN7, VALUE(3), 2 }, 4335 { SENSORS_PC87360_IN8, "in8", NOMAP, NOMAP, R, 4336 PC87365_SYSCTL_IN8, VALUE(3), 2 }, 4337 { SENSORS_PC87360_IN9, "in9", NOMAP, NOMAP, R, 4338 PC87365_SYSCTL_IN9, VALUE(3), 2 }, 4339 { SENSORS_PC87360_IN10, "in10", NOMAP, NOMAP, R, 4340 PC87365_SYSCTL_IN10, VALUE(3), 2 }, 4341 { SENSORS_PC87360_IN0_MIN, "in0_min", SENSORS_PC87360_IN0, 4342 SENSORS_PC87360_IN0, RW, PC87365_SYSCTL_IN0, 4343 VALUE(1), 2 }, 4344 { SENSORS_PC87360_IN1_MIN, "in1_min", SENSORS_PC87360_IN1, 4345 SENSORS_PC87360_IN1, RW, PC87365_SYSCTL_IN1, 4346 VALUE(1), 2 }, 4347 { SENSORS_PC87360_IN2_MIN, "in2_min", SENSORS_PC87360_IN2, 4348 SENSORS_PC87360_IN2, RW, PC87365_SYSCTL_IN2, 4349 VALUE(1), 2 }, 4350 { SENSORS_PC87360_IN3_MIN, "in3_min", SENSORS_PC87360_IN3, 4351 SENSORS_PC87360_IN3, RW, PC87365_SYSCTL_IN3, 4352 VALUE(1), 2 }, 4353 { SENSORS_PC87360_IN4_MIN, "in4_min", SENSORS_PC87360_IN4, 4354 SENSORS_PC87360_IN4, RW, PC87365_SYSCTL_IN4, 4355 VALUE(1), 2 }, 4356 { SENSORS_PC87360_IN5_MIN, "in5_min", SENSORS_PC87360_IN5, 4357 SENSORS_PC87360_IN5, RW, PC87365_SYSCTL_IN5, 4358 VALUE(1), 2 }, 4359 { SENSORS_PC87360_IN6_MIN, "in6_min", SENSORS_PC87360_IN6, 4360 SENSORS_PC87360_IN6, RW, PC87365_SYSCTL_IN6, 4361 VALUE(1), 2 }, 4362 { SENSORS_PC87360_IN7_MIN, "in7_min", SENSORS_PC87360_IN7, 4363 SENSORS_PC87360_IN7, RW, PC87365_SYSCTL_IN7, 4364 VALUE(1), 2 }, 4365 { SENSORS_PC87360_IN8_MIN, "in8_min", SENSORS_PC87360_IN8, 4366 SENSORS_PC87360_IN8, RW, PC87365_SYSCTL_IN8, 4367 VALUE(1), 2 }, 4368 { SENSORS_PC87360_IN9_MIN, "in9_min", SENSORS_PC87360_IN9, 4369 SENSORS_PC87360_IN9, RW, PC87365_SYSCTL_IN9,
