diff options
Diffstat (limited to 'drivers/hwmon/via686a.c')
| -rw-r--r-- | drivers/hwmon/via686a.c | 538 | 
1 files changed, 268 insertions, 270 deletions
| diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 9a440c8cc520..24a6851491d0 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c | |||
| @@ -34,9 +34,9 @@ | |||
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> | 
| 35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> | 
| 36 | #include <linux/jiffies.h> | 36 | #include <linux/jiffies.h> | 
| 37 | #include <linux/i2c.h> | 37 | #include <linux/platform_device.h> | 
| 38 | #include <linux/i2c-isa.h> | ||
| 39 | #include <linux/hwmon.h> | 38 | #include <linux/hwmon.h> | 
| 39 | #include <linux/hwmon-sysfs.h> | ||
| 40 | #include <linux/err.h> | 40 | #include <linux/err.h> | 
| 41 | #include <linux/init.h> | 41 | #include <linux/init.h> | 
| 42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> | 
| @@ -51,10 +51,7 @@ module_param(force_addr, ushort, 0); | |||
| 51 | MODULE_PARM_DESC(force_addr, | 51 | MODULE_PARM_DESC(force_addr, | 
| 52 | "Initialize the base address of the sensors"); | 52 | "Initialize the base address of the sensors"); | 
| 53 | 53 | ||
| 54 | /* Device address | 54 | static struct platform_device *pdev; | 
| 55 | Note that we can't determine the ISA address until we have initialized | ||
| 56 | our module */ | ||
| 57 | static unsigned short address; | ||
| 58 | 55 | ||
| 59 | /* | 56 | /* | 
| 60 | The Via 686a southbridge has a LM78-like chip integrated on the same IC. | 57 | The Via 686a southbridge has a LM78-like chip integrated on the same IC. | 
| @@ -295,7 +292,8 @@ static inline long TEMP_FROM_REG10(u16 val) | |||
| 295 | /* For each registered chip, we need to keep some data in memory. | 292 | /* For each registered chip, we need to keep some data in memory. | 
| 296 | The structure is dynamically allocated. */ | 293 | The structure is dynamically allocated. */ | 
| 297 | struct via686a_data { | 294 | struct via686a_data { | 
| 298 | struct i2c_client client; | 295 | unsigned short addr; | 
| 296 | const char *name; | ||
| 299 | struct class_device *class_dev; | 297 | struct class_device *class_dev; | 
| 300 | struct mutex update_lock; | 298 | struct mutex update_lock; | 
| 301 | char valid; /* !=0 if following fields are valid */ | 299 | char valid; /* !=0 if following fields are valid */ | 
| @@ -315,98 +313,85 @@ struct via686a_data { | |||
| 315 | 313 | ||
| 316 | static struct pci_dev *s_bridge; /* pointer to the (only) via686a */ | 314 | static struct pci_dev *s_bridge; /* pointer to the (only) via686a */ | 
| 317 | 315 | ||
| 318 | static int via686a_detect(struct i2c_adapter *adapter); | 316 | static int via686a_probe(struct platform_device *pdev); | 
| 319 | static int via686a_detach_client(struct i2c_client *client); | 317 | static int via686a_remove(struct platform_device *pdev); | 
| 320 | 318 | ||
| 321 | static inline int via686a_read_value(struct i2c_client *client, u8 reg) | 319 | static inline int via686a_read_value(struct via686a_data *data, u8 reg) | 
| 322 | { | 320 | { | 
| 323 | return (inb_p(client->addr + reg)); | 321 | return inb_p(data->addr + reg); | 
| 324 | } | 322 | } | 
| 325 | 323 | ||
| 326 | static inline void via686a_write_value(struct i2c_client *client, u8 reg, | 324 | static inline void via686a_write_value(struct via686a_data *data, u8 reg, | 
| 327 | u8 value) | 325 | u8 value) | 
| 328 | { | 326 | { | 
| 329 | outb_p(value, client->addr + reg); | 327 | outb_p(value, data->addr + reg); | 
| 330 | } | 328 | } | 
| 331 | 329 | ||
| 332 | static struct via686a_data *via686a_update_device(struct device *dev); | 330 | static struct via686a_data *via686a_update_device(struct device *dev); | 
| 333 | static void via686a_init_client(struct i2c_client *client); | 331 | static void via686a_init_device(struct via686a_data *data); | 
| 334 | 332 | ||
| 335 | /* following are the sysfs callback functions */ | 333 | /* following are the sysfs callback functions */ | 
| 336 | 334 | ||
| 337 | /* 7 voltage sensors */ | 335 | /* 7 voltage sensors */ | 
| 338 | static ssize_t show_in(struct device *dev, char *buf, int nr) { | 336 | static ssize_t show_in(struct device *dev, struct device_attribute *da, | 
| 337 | char *buf) { | ||
| 339 | struct via686a_data *data = via686a_update_device(dev); | 338 | struct via686a_data *data = via686a_update_device(dev); | 
| 339 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 340 | int nr = attr->index; | ||
| 340 | return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)); | 341 | return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)); | 
| 341 | } | 342 | } | 
| 342 | 343 | ||
| 343 | static ssize_t show_in_min(struct device *dev, char *buf, int nr) { | 344 | static ssize_t show_in_min(struct device *dev, struct device_attribute *da, | 
| 345 | char *buf) { | ||
| 344 | struct via686a_data *data = via686a_update_device(dev); | 346 | struct via686a_data *data = via686a_update_device(dev); | 
| 347 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 348 | int nr = attr->index; | ||
| 345 | return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)); | 349 | return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)); | 
| 346 | } | 350 | } | 
| 347 | 351 | ||
| 348 | static ssize_t show_in_max(struct device *dev, char *buf, int nr) { | 352 | static ssize_t show_in_max(struct device *dev, struct device_attribute *da, | 
| 353 | char *buf) { | ||
| 349 | struct via686a_data *data = via686a_update_device(dev); | 354 | struct via686a_data *data = via686a_update_device(dev); | 
| 355 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 356 | int nr = attr->index; | ||
| 350 | return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)); | 357 | return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)); | 
| 351 | } | 358 | } | 
| 352 | 359 | ||
| 353 | static ssize_t set_in_min(struct device *dev, const char *buf, | 360 | static ssize_t set_in_min(struct device *dev, struct device_attribute *da, | 
| 354 | size_t count, int nr) { | 361 | const char *buf, size_t count) { | 
| 355 | struct i2c_client *client = to_i2c_client(dev); | 362 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 356 | struct via686a_data *data = i2c_get_clientdata(client); | 363 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 
| 364 | int nr = attr->index; | ||
| 357 | unsigned long val = simple_strtoul(buf, NULL, 10); | 365 | unsigned long val = simple_strtoul(buf, NULL, 10); | 
| 358 | 366 | ||
| 359 | mutex_lock(&data->update_lock); | 367 | mutex_lock(&data->update_lock); | 
| 360 | data->in_min[nr] = IN_TO_REG(val, nr); | 368 | data->in_min[nr] = IN_TO_REG(val, nr); | 
| 361 | via686a_write_value(client, VIA686A_REG_IN_MIN(nr), | 369 | via686a_write_value(data, VIA686A_REG_IN_MIN(nr), | 
| 362 | data->in_min[nr]); | 370 | data->in_min[nr]); | 
| 363 | mutex_unlock(&data->update_lock); | 371 | mutex_unlock(&data->update_lock); | 
| 364 | return count; | 372 | return count; | 
| 365 | } | 373 | } | 
| 366 | static ssize_t set_in_max(struct device *dev, const char *buf, | 374 | static ssize_t set_in_max(struct device *dev, struct device_attribute *da, | 
| 367 | size_t count, int nr) { | 375 | const char *buf, size_t count) { | 
| 368 | struct i2c_client *client = to_i2c_client(dev); | 376 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 369 | struct via686a_data *data = i2c_get_clientdata(client); | 377 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 
| 378 | int nr = attr->index; | ||
| 370 | unsigned long val = simple_strtoul(buf, NULL, 10); | 379 | unsigned long val = simple_strtoul(buf, NULL, 10); | 
| 371 | 380 | ||
| 372 | mutex_lock(&data->update_lock); | 381 | mutex_lock(&data->update_lock); | 
| 373 | data->in_max[nr] = IN_TO_REG(val, nr); | 382 | data->in_max[nr] = IN_TO_REG(val, nr); | 
| 374 | via686a_write_value(client, VIA686A_REG_IN_MAX(nr), | 383 | via686a_write_value(data, VIA686A_REG_IN_MAX(nr), | 
| 375 | data->in_max[nr]); | 384 | data->in_max[nr]); | 
| 376 | mutex_unlock(&data->update_lock); | 385 | mutex_unlock(&data->update_lock); | 
| 377 | return count; | 386 | return count; | 
| 378 | } | 387 | } | 
| 379 | #define show_in_offset(offset) \ | 388 | #define show_in_offset(offset) \ | 
| 380 | static ssize_t \ | 389 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ | 
| 381 | show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 390 | show_in, NULL, offset); \ | 
| 382 | { \ | 391 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | 
| 383 | return show_in(dev, buf, offset); \ | 392 | show_in_min, set_in_min, offset); \ | 
| 384 | } \ | 393 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | 
| 385 | static ssize_t \ | 394 | show_in_max, set_in_max, offset); | 
| 386 | show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 387 | { \ | ||
| 388 | return show_in_min(dev, buf, offset); \ | ||
| 389 | } \ | ||
| 390 | static ssize_t \ | ||
| 391 | show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 392 | { \ | ||
| 393 | return show_in_max(dev, buf, offset); \ | ||
| 394 | } \ | ||
| 395 | static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \ | ||
| 396 | const char *buf, size_t count) \ | ||
| 397 | { \ | ||
| 398 | return set_in_min(dev, buf, count, offset); \ | ||
| 399 | } \ | ||
| 400 | static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \ | ||
| 401 | const char *buf, size_t count) \ | ||
| 402 | { \ | ||
| 403 | return set_in_max(dev, buf, count, offset); \ | ||
| 404 | } \ | ||
| 405 | static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\ | ||
| 406 | static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | ||
| 407 | show_in##offset##_min, set_in##offset##_min); \ | ||
| 408 | static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | ||
| 409 | show_in##offset##_max, set_in##offset##_max); | ||
| 410 | 395 | ||
| 411 | show_in_offset(0); | 396 | show_in_offset(0); | 
| 412 | show_in_offset(1); | 397 | show_in_offset(1); | 
| @@ -415,150 +400,128 @@ show_in_offset(3); | |||
| 415 | show_in_offset(4); | 400 | show_in_offset(4); | 
| 416 | 401 | ||
| 417 | /* 3 temperatures */ | 402 | /* 3 temperatures */ | 
| 418 | static ssize_t show_temp(struct device *dev, char *buf, int nr) { | 403 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, | 
| 404 | char *buf) { | ||
| 419 | struct via686a_data *data = via686a_update_device(dev); | 405 | struct via686a_data *data = via686a_update_device(dev); | 
| 406 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 407 | int nr = attr->index; | ||
| 420 | return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])); | 408 | return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])); | 
| 421 | } | 409 | } | 
| 422 | static ssize_t show_temp_over(struct device *dev, char *buf, int nr) { | 410 | static ssize_t show_temp_over(struct device *dev, struct device_attribute *da, | 
| 411 | char *buf) { | ||
| 423 | struct via686a_data *data = via686a_update_device(dev); | 412 | struct via686a_data *data = via686a_update_device(dev); | 
| 413 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 414 | int nr = attr->index; | ||
| 424 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])); | 415 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])); | 
| 425 | } | 416 | } | 
| 426 | static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) { | 417 | static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da, | 
| 418 | char *buf) { | ||
| 427 | struct via686a_data *data = via686a_update_device(dev); | 419 | struct via686a_data *data = via686a_update_device(dev); | 
| 420 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 421 | int nr = attr->index; | ||
| 428 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])); | 422 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])); | 
| 429 | } | 423 | } | 
| 430 | static ssize_t set_temp_over(struct device *dev, const char *buf, | 424 | static ssize_t set_temp_over(struct device *dev, struct device_attribute *da, | 
| 431 | size_t count, int nr) { | 425 | const char *buf, size_t count) { | 
| 432 | struct i2c_client *client = to_i2c_client(dev); | 426 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 433 | struct via686a_data *data = i2c_get_clientdata(client); | 427 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 
| 428 | int nr = attr->index; | ||
| 434 | int val = simple_strtol(buf, NULL, 10); | 429 | int val = simple_strtol(buf, NULL, 10); | 
| 435 | 430 | ||
| 436 | mutex_lock(&data->update_lock); | 431 | mutex_lock(&data->update_lock); | 
| 437 | data->temp_over[nr] = TEMP_TO_REG(val); | 432 | data->temp_over[nr] = TEMP_TO_REG(val); | 
| 438 | via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], | 433 | via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr], | 
| 439 | data->temp_over[nr]); | 434 | data->temp_over[nr]); | 
| 440 | mutex_unlock(&data->update_lock); | 435 | mutex_unlock(&data->update_lock); | 
| 441 | return count; | 436 | return count; | 
| 442 | } | 437 | } | 
| 443 | static ssize_t set_temp_hyst(struct device *dev, const char *buf, | 438 | static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da, | 
| 444 | size_t count, int nr) { | 439 | const char *buf, size_t count) { | 
| 445 | struct i2c_client *client = to_i2c_client(dev); | 440 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 446 | struct via686a_data *data = i2c_get_clientdata(client); | 441 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 
| 442 | int nr = attr->index; | ||
| 447 | int val = simple_strtol(buf, NULL, 10); | 443 | int val = simple_strtol(buf, NULL, 10); | 
| 448 | 444 | ||
| 449 | mutex_lock(&data->update_lock); | 445 | mutex_lock(&data->update_lock); | 
| 450 | data->temp_hyst[nr] = TEMP_TO_REG(val); | 446 | data->temp_hyst[nr] = TEMP_TO_REG(val); | 
| 451 | via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], | 447 | via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr], | 
| 452 | data->temp_hyst[nr]); | 448 | data->temp_hyst[nr]); | 
| 453 | mutex_unlock(&data->update_lock); | 449 | mutex_unlock(&data->update_lock); | 
| 454 | return count; | 450 | return count; | 
| 455 | } | 451 | } | 
| 456 | #define show_temp_offset(offset) \ | 452 | #define show_temp_offset(offset) \ | 
| 457 | static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 453 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ | 
| 458 | { \ | 454 | show_temp, NULL, offset - 1); \ | 
| 459 | return show_temp(dev, buf, offset - 1); \ | 455 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | 
| 460 | } \ | 456 | show_temp_over, set_temp_over, offset - 1); \ | 
| 461 | static ssize_t \ | 457 | static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ | 
| 462 | show_temp_##offset##_over (struct device *dev, struct device_attribute *attr, char *buf) \ | 458 | show_temp_hyst, set_temp_hyst, offset - 1); | 
| 463 | { \ | ||
| 464 | return show_temp_over(dev, buf, offset - 1); \ | ||
| 465 | } \ | ||
| 466 | static ssize_t \ | ||
| 467 | show_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 468 | { \ | ||
| 469 | return show_temp_hyst(dev, buf, offset - 1); \ | ||
| 470 | } \ | ||
| 471 | static ssize_t set_temp_##offset##_over (struct device *dev, struct device_attribute *attr, \ | ||
| 472 | const char *buf, size_t count) \ | ||
| 473 | { \ | ||
| 474 | return set_temp_over(dev, buf, count, offset - 1); \ | ||
| 475 | } \ | ||
| 476 | static ssize_t set_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, \ | ||
| 477 | const char *buf, size_t count) \ | ||
| 478 | { \ | ||
| 479 | return set_temp_hyst(dev, buf, count, offset - 1); \ | ||
| 480 | } \ | ||
| 481 | static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\ | ||
| 482 | static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | ||
| 483 | show_temp_##offset##_over, set_temp_##offset##_over); \ | ||
| 484 | static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ | ||
| 485 | show_temp_##offset##_hyst, set_temp_##offset##_hyst); | ||
| 486 | 459 | ||
| 487 | show_temp_offset(1); | 460 | show_temp_offset(1); | 
| 488 | show_temp_offset(2); | 461 | show_temp_offset(2); | 
| 489 | show_temp_offset(3); | 462 | show_temp_offset(3); | 
| 490 | 463 | ||
| 491 | /* 2 Fans */ | 464 | /* 2 Fans */ | 
| 492 | static ssize_t show_fan(struct device *dev, char *buf, int nr) { | 465 | static ssize_t show_fan(struct device *dev, struct device_attribute *da, | 
| 466 | char *buf) { | ||
| 493 | struct via686a_data *data = via686a_update_device(dev); | 467 | struct via686a_data *data = via686a_update_device(dev); | 
| 468 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 469 | int nr = attr->index; | ||
| 494 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], | 470 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], | 
| 495 | DIV_FROM_REG(data->fan_div[nr])) ); | 471 | DIV_FROM_REG(data->fan_div[nr])) ); | 
| 496 | } | 472 | } | 
| 497 | static ssize_t show_fan_min(struct device *dev, char *buf, int nr) { | 473 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, | 
| 474 | char *buf) { | ||
| 498 | struct via686a_data *data = via686a_update_device(dev); | 475 | struct via686a_data *data = via686a_update_device(dev); | 
| 476 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 477 | int nr = attr->index; | ||
| 499 | return sprintf(buf, "%d\n", | 478 | return sprintf(buf, "%d\n", | 
| 500 | FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) ); | 479 | FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) ); | 
| 501 | } | 480 | } | 
| 502 | static ssize_t show_fan_div(struct device *dev, char *buf, int nr) { | 481 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, | 
| 482 | char *buf) { | ||
| 503 | struct via686a_data *data = via686a_update_device(dev); | 483 | struct via686a_data *data = via686a_update_device(dev); | 
| 484 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 485 | int nr = attr->index; | ||
| 504 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) ); | 486 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) ); | 
| 505 | } | 487 | } | 
| 506 | static ssize_t set_fan_min(struct device *dev, const char *buf, | 488 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, | 
| 507 | size_t count, int nr) { | 489 | const char *buf, size_t count) { | 
| 508 | struct i2c_client *client = to_i2c_client(dev); | 490 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 509 | struct via686a_data *data = i2c_get_clientdata(client); | 491 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 
| 492 | int nr = attr->index; | ||
| 510 | int val = simple_strtol(buf, NULL, 10); | 493 | int val = simple_strtol(buf, NULL, 10); | 
| 511 | 494 | ||
| 512 | mutex_lock(&data->update_lock); | 495 | mutex_lock(&data->update_lock); | 
| 513 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 496 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 
| 514 | via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); | 497 | via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); | 
| 515 | mutex_unlock(&data->update_lock); | 498 | mutex_unlock(&data->update_lock); | 
| 516 | return count; | 499 | return count; | 
| 517 | } | 500 | } | 
| 518 | static ssize_t set_fan_div(struct device *dev, const char *buf, | 501 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, | 
| 519 | size_t count, int nr) { | 502 | const char *buf, size_t count) { | 
| 520 | struct i2c_client *client = to_i2c_client(dev); | 503 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 521 | struct via686a_data *data = i2c_get_clientdata(client); | 504 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 
| 505 | int nr = attr->index; | ||
| 522 | int val = simple_strtol(buf, NULL, 10); | 506 | int val = simple_strtol(buf, NULL, 10); | 
| 523 | int old; | 507 | int old; | 
| 524 | 508 | ||
| 525 | mutex_lock(&data->update_lock); | 509 | mutex_lock(&data->update_lock); | 
| 526 | old = via686a_read_value(client, VIA686A_REG_FANDIV); | 510 | old = via686a_read_value(data, VIA686A_REG_FANDIV); | 
| 527 | data->fan_div[nr] = DIV_TO_REG(val); | 511 | data->fan_div[nr] = DIV_TO_REG(val); | 
| 528 | old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); | 512 | old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); | 
| 529 | via686a_write_value(client, VIA686A_REG_FANDIV, old); | 513 | via686a_write_value(data, VIA686A_REG_FANDIV, old); | 
| 530 | mutex_unlock(&data->update_lock); | 514 | mutex_unlock(&data->update_lock); | 
| 531 | return count; | 515 | return count; | 
| 532 | } | 516 | } | 
| 533 | 517 | ||
| 534 | #define show_fan_offset(offset) \ | 518 | #define show_fan_offset(offset) \ | 
| 535 | static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ | 519 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 
| 536 | { \ | 520 | show_fan, NULL, offset - 1); \ | 
| 537 | return show_fan(dev, buf, offset - 1); \ | 521 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | 
| 538 | } \ | 522 | show_fan_min, set_fan_min, offset - 1); \ | 
| 539 | static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ | 523 | static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | 
| 540 | { \ | 524 | show_fan_div, set_fan_div, offset - 1); | 
| 541 | return show_fan_min(dev, buf, offset - 1); \ | ||
| 542 | } \ | ||
| 543 | static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ | ||
| 544 | { \ | ||
| 545 | return show_fan_div(dev, buf, offset - 1); \ | ||
| 546 | } \ | ||
| 547 | static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ | ||
| 548 | const char *buf, size_t count) \ | ||
| 549 | { \ | ||
| 550 | return set_fan_min(dev, buf, count, offset - 1); \ | ||
| 551 | } \ | ||
| 552 | static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, \ | ||
| 553 | const char *buf, size_t count) \ | ||
| 554 | { \ | ||
| 555 | return set_fan_div(dev, buf, count, offset - 1); \ | ||
| 556 | } \ | ||
| 557 | static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ | ||
| 558 | static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
| 559 | show_fan_##offset##_min, set_fan_##offset##_min); \ | ||
| 560 | static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | ||
| 561 | show_fan_##offset##_div, set_fan_##offset##_div); | ||
| 562 | 525 | ||
| 563 | show_fan_offset(1); | 526 | show_fan_offset(1); | 
| 564 | show_fan_offset(2); | 527 | show_fan_offset(2); | 
| @@ -570,41 +533,50 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch | |||
| 570 | } | 533 | } | 
| 571 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 534 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 
| 572 | 535 | ||
| 536 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
| 537 | *devattr, char *buf) | ||
| 538 | { | ||
| 539 | struct via686a_data *data = dev_get_drvdata(dev); | ||
| 540 | return sprintf(buf, "%s\n", data->name); | ||
| 541 | } | ||
| 542 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
| 543 | |||
| 573 | static struct attribute *via686a_attributes[] = { | 544 | static struct attribute *via686a_attributes[] = { | 
| 574 | &dev_attr_in0_input.attr, | 545 | &sensor_dev_attr_in0_input.dev_attr.attr, | 
| 575 | &dev_attr_in1_input.attr, | 546 | &sensor_dev_attr_in1_input.dev_attr.attr, | 
| 576 | &dev_attr_in2_input.attr, | 547 | &sensor_dev_attr_in2_input.dev_attr.attr, | 
| 577 | &dev_attr_in3_input.attr, | 548 | &sensor_dev_attr_in3_input.dev_attr.attr, | 
| 578 | &dev_attr_in4_input.attr, | 549 | &sensor_dev_attr_in4_input.dev_attr.attr, | 
| 579 | &dev_attr_in0_min.attr, | 550 | &sensor_dev_attr_in0_min.dev_attr.attr, | 
| 580 | &dev_attr_in1_min.attr, | 551 | &sensor_dev_attr_in1_min.dev_attr.attr, | 
| 581 | &dev_attr_in2_min.attr, | 552 | &sensor_dev_attr_in2_min.dev_attr.attr, | 
| 582 | &dev_attr_in3_min.attr, | 553 | &sensor_dev_attr_in3_min.dev_attr.attr, | 
| 583 | &dev_attr_in4_min.attr, | 554 | &sensor_dev_attr_in4_min.dev_attr.attr, | 
| 584 | &dev_attr_in0_max.attr, | 555 | &sensor_dev_attr_in0_max.dev_attr.attr, | 
| 585 | &dev_attr_in1_max.attr, | 556 | &sensor_dev_attr_in1_max.dev_attr.attr, | 
| 586 | &dev_attr_in2_max.attr, | 557 | &sensor_dev_attr_in2_max.dev_attr.attr, | 
| 587 | &dev_attr_in3_max.attr, | 558 | &sensor_dev_attr_in3_max.dev_attr.attr, | 
| 588 | &dev_attr_in4_max.attr, | 559 | &sensor_dev_attr_in4_max.dev_attr.attr, | 
| 589 | 560 | ||
| 590 | &dev_attr_temp1_input.attr, | 561 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 
| 591 | &dev_attr_temp2_input.attr, | 562 | &sensor_dev_attr_temp2_input.dev_attr.attr, | 
| 592 | &dev_attr_temp3_input.attr, | 563 | &sensor_dev_attr_temp3_input.dev_attr.attr, | 
| 593 | &dev_attr_temp1_max.attr, | 564 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 
| 594 | &dev_attr_temp2_max.attr, | 565 | &sensor_dev_attr_temp2_max.dev_attr.attr, | 
| 595 | &dev_attr_temp3_max.attr, | 566 | &sensor_dev_attr_temp3_max.dev_attr.attr, | 
| 596 | &dev_attr_temp1_max_hyst.attr, | 567 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | 
| 597 | &dev_attr_temp2_max_hyst.attr, | 568 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, | 
| 598 | &dev_attr_temp3_max_hyst.attr, | 569 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, | 
| 599 | 570 | ||
| 600 | &dev_attr_fan1_input.attr, | 571 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 
| 601 | &dev_attr_fan2_input.attr, | 572 | &sensor_dev_attr_fan2_input.dev_attr.attr, | 
| 602 | &dev_attr_fan1_min.attr, | 573 | &sensor_dev_attr_fan1_min.dev_attr.attr, | 
| 603 | &dev_attr_fan2_min.attr, | 574 | &sensor_dev_attr_fan2_min.dev_attr.attr, | 
| 604 | &dev_attr_fan1_div.attr, | 575 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 
| 605 | &dev_attr_fan2_div.attr, | 576 | &sensor_dev_attr_fan2_div.dev_attr.attr, | 
| 606 | 577 | ||
| 607 | &dev_attr_alarms.attr, | 578 | &dev_attr_alarms.attr, | 
| 579 | &dev_attr_name.attr, | ||
| 608 | NULL | 580 | NULL | 
| 609 | }; | 581 | }; | 
| 610 | 582 | ||
| @@ -612,58 +584,29 @@ static const struct attribute_group via686a_group = { | |||
| 612 | .attrs = via686a_attributes, | 584 | .attrs = via686a_attributes, | 
| 613 | }; | 585 | }; | 
| 614 | 586 | ||
| 615 | /* The driver. I choose to use type i2c_driver, as at is identical to both | 587 | static struct platform_driver via686a_driver = { | 
| 616 | smbus_driver and isa_driver, and clients could be of either kind */ | ||
| 617 | static struct i2c_driver via686a_driver = { | ||
| 618 | .driver = { | 588 | .driver = { | 
| 619 | .owner = THIS_MODULE, | 589 | .owner = THIS_MODULE, | 
| 620 | .name = "via686a", | 590 | .name = "via686a", | 
| 621 | }, | 591 | }, | 
| 622 | .attach_adapter = via686a_detect, | 592 | .probe = via686a_probe, | 
| 623 | .detach_client = via686a_detach_client, | 593 | .remove = __devexit_p(via686a_remove), | 
| 624 | }; | 594 | }; | 
| 625 | 595 | ||
| 626 | 596 | ||
| 627 | /* This is called when the module is loaded */ | 597 | /* This is called when the module is loaded */ | 
| 628 | static int via686a_detect(struct i2c_adapter *adapter) | 598 | static int __devinit via686a_probe(struct platform_device *pdev) | 
| 629 | { | 599 | { | 
| 630 | struct i2c_client *new_client; | ||
| 631 | struct via686a_data *data; | 600 | struct via686a_data *data; | 
| 632 | int err = 0; | 601 | struct resource *res; | 
| 633 | const char client_name[] = "via686a"; | 602 | int err; | 
| 634 | u16 val; | ||
| 635 | |||
| 636 | /* 8231 requires multiple of 256, we enforce that on 686 as well */ | ||
| 637 | if (force_addr) { | ||
| 638 | address = force_addr & 0xFF00; | ||
| 639 | dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", | ||
| 640 | address); | ||
| 641 | if (PCIBIOS_SUCCESSFUL != | ||
| 642 | pci_write_config_word(s_bridge, VIA686A_BASE_REG, address)) | ||
| 643 | return -ENODEV; | ||
| 644 | } | ||
| 645 | if (PCIBIOS_SUCCESSFUL != | ||
| 646 | pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val)) | ||
| 647 | return -ENODEV; | ||
| 648 | if (!(val & 0x0001)) { | ||
| 649 | if (force_addr) { | ||
| 650 | dev_info(&adapter->dev, "enabling sensors\n"); | ||
| 651 | if (PCIBIOS_SUCCESSFUL != | ||
| 652 | pci_write_config_word(s_bridge, VIA686A_ENABLE_REG, | ||
| 653 | val | 0x0001)) | ||
| 654 | return -ENODEV; | ||
| 655 | } else { | ||
| 656 | dev_warn(&adapter->dev, "sensors disabled - enable " | ||
| 657 | "with force_addr=0x%x\n", address); | ||
| 658 | return -ENODEV; | ||
| 659 | } | ||
| 660 | } | ||
| 661 | 603 | ||
| 662 | /* Reserve the ISA region */ | 604 | /* Reserve the ISA region */ | 
| 663 | if (!request_region(address, VIA686A_EXTENT, | 605 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 
| 606 | if (!request_region(res->start, VIA686A_EXTENT, | ||
| 664 | via686a_driver.driver.name)) { | 607 | via686a_driver.driver.name)) { | 
| 665 | dev_err(&adapter->dev, "region 0x%x already in use!\n", | 608 | dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n", | 
| 666 | address); | 609 | (unsigned long)res->start, (unsigned long)res->end); | 
| 667 | return -ENODEV; | 610 | return -ENODEV; | 
| 668 | } | 611 | } | 
| 669 | 612 | ||
| @@ -672,30 +615,19 @@ static int via686a_detect(struct i2c_adapter *adapter) | |||
| 672 | goto exit_release; | 615 | goto exit_release; | 
| 673 | } | 616 | } | 
| 674 | 617 | ||
| 675 | new_client = &data->client; | 618 | platform_set_drvdata(pdev, data); | 
| 676 | i2c_set_clientdata(new_client, data); | 619 | data->addr = res->start; | 
| 677 | new_client->addr = address; | 620 | data->name = "via686a"; | 
| 678 | new_client->adapter = adapter; | ||
| 679 | new_client->driver = &via686a_driver; | ||
| 680 | new_client->flags = 0; | ||
| 681 | |||
| 682 | /* Fill in the remaining client fields and put into the global list */ | ||
| 683 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); | ||
| 684 | |||
| 685 | data->valid = 0; | ||
| 686 | mutex_init(&data->update_lock); | 621 | mutex_init(&data->update_lock); | 
| 687 | /* Tell the I2C layer a new client has arrived */ | ||
| 688 | if ((err = i2c_attach_client(new_client))) | ||
| 689 | goto exit_free; | ||
| 690 | 622 | ||
| 691 | /* Initialize the VIA686A chip */ | 623 | /* Initialize the VIA686A chip */ | 
| 692 | via686a_init_client(new_client); | 624 | via686a_init_device(data); | 
| 693 | 625 | ||
| 694 | /* Register sysfs hooks */ | 626 | /* Register sysfs hooks */ | 
| 695 | if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group))) | 627 | if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group))) | 
| 696 | goto exit_detach; | 628 | goto exit_free; | 
| 697 | 629 | ||
| 698 | data->class_dev = hwmon_device_register(&new_client->dev); | 630 | data->class_dev = hwmon_device_register(&pdev->dev); | 
| 699 | if (IS_ERR(data->class_dev)) { | 631 | if (IS_ERR(data->class_dev)) { | 
| 700 | err = PTR_ERR(data->class_dev); | 632 | err = PTR_ERR(data->class_dev); | 
| 701 | goto exit_remove_files; | 633 | goto exit_remove_files; | 
| @@ -704,51 +636,46 @@ static int via686a_detect(struct i2c_adapter *adapter) | |||
| 704 | return 0; | 636 | return 0; | 
| 705 | 637 | ||
| 706 | exit_remove_files: | 638 | exit_remove_files: | 
| 707 | sysfs_remove_group(&new_client->dev.kobj, &via686a_group); | 639 | sysfs_remove_group(&pdev->dev.kobj, &via686a_group); | 
| 708 | exit_detach: | ||
| 709 | i2c_detach_client(new_client); | ||
| 710 | exit_free: | 640 | exit_free: | 
| 711 | kfree(data); | 641 | kfree(data); | 
| 712 | exit_release: | 642 | exit_release: | 
| 713 | release_region(address, VIA686A_EXTENT); | 643 | release_region(res->start, VIA686A_EXTENT); | 
| 714 | return err; | 644 | return err; | 
| 715 | } | 645 | } | 
| 716 | 646 | ||
| 717 | static int via686a_detach_client(struct i2c_client *client) | 647 | static int __devexit via686a_remove(struct platform_device *pdev) | 
| 718 | { | 648 | { | 
| 719 | struct via686a_data *data = i2c_get_clientdata(client); | 649 | struct via686a_data *data = platform_get_drvdata(pdev); | 
| 720 | int err; | ||
| 721 | 650 | ||
| 722 | hwmon_device_unregister(data->class_dev); | 651 | hwmon_device_unregister(data->class_dev); | 
| 723 | sysfs_remove_group(&client->dev.kobj, &via686a_group); | 652 | sysfs_remove_group(&pdev->dev.kobj, &via686a_group); | 
| 724 | 653 | ||
| 725 | if ((err = i2c_detach_client(client))) | 654 | release_region(data->addr, VIA686A_EXTENT); | 
| 726 | return err; | 655 | platform_set_drvdata(pdev, NULL); | 
| 727 | |||
| 728 | release_region(client->addr, VIA686A_EXTENT); | ||
| 729 | kfree(data); | 656 | kfree(data); | 
| 730 | 657 | ||
| 731 | return 0; | 658 | return 0; | 
| 732 | } | 659 | } | 
| 733 | 660 | ||
| 734 | static void via686a_init_client(struct i2c_client *client) | 661 | static void __devinit via686a_init_device(struct via686a_data *data) | 
| 735 | { | 662 | { | 
| 736 | u8 reg; | 663 | u8 reg; | 
| 737 | 664 | ||
| 738 | /* Start monitoring */ | 665 | /* Start monitoring */ | 
| 739 | reg = via686a_read_value(client, VIA686A_REG_CONFIG); | 666 | reg = via686a_read_value(data, VIA686A_REG_CONFIG); | 
| 740 | via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F); | 667 | via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F); | 
| 741 | 668 | ||
| 742 | /* Configure temp interrupt mode for continuous-interrupt operation */ | 669 | /* Configure temp interrupt mode for continuous-interrupt operation */ | 
| 743 | via686a_write_value(client, VIA686A_REG_TEMP_MODE, | 670 | reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE); | 
| 744 | via686a_read_value(client, VIA686A_REG_TEMP_MODE) & | 671 | via686a_write_value(data, VIA686A_REG_TEMP_MODE, | 
| 745 | !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS)); | 672 | (reg & ~VIA686A_TEMP_MODE_MASK) | 
| 673 | | VIA686A_TEMP_MODE_CONTINUOUS); | ||
| 746 | } | 674 | } | 
| 747 | 675 | ||
| 748 | static struct via686a_data *via686a_update_device(struct device *dev) | 676 | static struct via686a_data *via686a_update_device(struct device *dev) | 
| 749 | { | 677 | { | 
| 750 | struct i2c_client *client = to_i2c_client(dev); | 678 | struct via686a_data *data = dev_get_drvdata(dev); | 
| 751 | struct via686a_data *data = i2c_get_clientdata(client); | ||
| 752 | int i; | 679 | int i; | 
| 753 | 680 | ||
| 754 | mutex_lock(&data->update_lock); | 681 | mutex_lock(&data->update_lock); | 
| @@ -757,27 +684,27 @@ static struct via686a_data *via686a_update_device(struct device *dev) | |||
| 757 | || !data->valid) { | 684 | || !data->valid) { | 
| 758 | for (i = 0; i <= 4; i++) { | 685 | for (i = 0; i <= 4; i++) { | 
| 759 | data->in[i] = | 686 | data->in[i] = | 
| 760 | via686a_read_value(client, VIA686A_REG_IN(i)); | 687 | via686a_read_value(data, VIA686A_REG_IN(i)); | 
| 761 | data->in_min[i] = via686a_read_value(client, | 688 | data->in_min[i] = via686a_read_value(data, | 
| 762 | VIA686A_REG_IN_MIN | 689 | VIA686A_REG_IN_MIN | 
| 763 | (i)); | 690 | (i)); | 
| 764 | data->in_max[i] = | 691 | data->in_max[i] = | 
| 765 | via686a_read_value(client, VIA686A_REG_IN_MAX(i)); | 692 | via686a_read_value(data, VIA686A_REG_IN_MAX(i)); | 
| 766 | } | 693 | } | 
| 767 | for (i = 1; i <= 2; i++) { | 694 | for (i = 1; i <= 2; i++) { | 
| 768 | data->fan[i - 1] = | 695 | data->fan[i - 1] = | 
| 769 | via686a_read_value(client, VIA686A_REG_FAN(i)); | 696 | via686a_read_value(data, VIA686A_REG_FAN(i)); | 
| 770 | data->fan_min[i - 1] = via686a_read_value(client, | 697 | data->fan_min[i - 1] = via686a_read_value(data, | 
| 771 | VIA686A_REG_FAN_MIN(i)); | 698 | VIA686A_REG_FAN_MIN(i)); | 
| 772 | } | 699 | } | 
| 773 | for (i = 0; i <= 2; i++) { | 700 | for (i = 0; i <= 2; i++) { | 
| 774 | data->temp[i] = via686a_read_value(client, | 701 | data->temp[i] = via686a_read_value(data, | 
| 775 | VIA686A_REG_TEMP[i]) << 2; | 702 | VIA686A_REG_TEMP[i]) << 2; | 
| 776 | data->temp_over[i] = | 703 | data->temp_over[i] = | 
| 777 | via686a_read_value(client, | 704 | via686a_read_value(data, | 
| 778 | VIA686A_REG_TEMP_OVER[i]); | 705 | VIA686A_REG_TEMP_OVER[i]); | 
| 779 | data->temp_hyst[i] = | 706 | data->temp_hyst[i] = | 
| 780 | via686a_read_value(client, | 707 | via686a_read_value(data, | 
| 781 | VIA686A_REG_TEMP_HYST[i]); | 708 | VIA686A_REG_TEMP_HYST[i]); | 
| 782 | } | 709 | } | 
| 783 | /* add in lower 2 bits | 710 | /* add in lower 2 bits | 
| @@ -785,23 +712,23 @@ static struct via686a_data *via686a_update_device(struct device *dev) | |||
| 785 | temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23 | 712 | temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23 | 
| 786 | temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23 | 713 | temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23 | 
| 787 | */ | 714 | */ | 
| 788 | data->temp[0] |= (via686a_read_value(client, | 715 | data->temp[0] |= (via686a_read_value(data, | 
| 789 | VIA686A_REG_TEMP_LOW1) | 716 | VIA686A_REG_TEMP_LOW1) | 
| 790 | & 0xc0) >> 6; | 717 | & 0xc0) >> 6; | 
| 791 | data->temp[1] |= | 718 | data->temp[1] |= | 
| 792 | (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) & | 719 | (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & | 
| 793 | 0x30) >> 4; | 720 | 0x30) >> 4; | 
| 794 | data->temp[2] |= | 721 | data->temp[2] |= | 
| 795 | (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) & | 722 | (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & | 
| 796 | 0xc0) >> 6; | 723 | 0xc0) >> 6; | 
| 797 | 724 | ||
| 798 | i = via686a_read_value(client, VIA686A_REG_FANDIV); | 725 | i = via686a_read_value(data, VIA686A_REG_FANDIV); | 
| 799 | data->fan_div[0] = (i >> 4) & 0x03; | 726 | data->fan_div[0] = (i >> 4) & 0x03; | 
| 800 | data->fan_div[1] = i >> 6; | 727 | data->fan_div[1] = i >> 6; | 
| 801 | data->alarms = | 728 | data->alarms = | 
| 802 | via686a_read_value(client, | 729 | via686a_read_value(data, | 
| 803 | VIA686A_REG_ALARM1) | | 730 | VIA686A_REG_ALARM1) | | 
| 804 | (via686a_read_value(client, VIA686A_REG_ALARM2) << 8); | 731 | (via686a_read_value(data, VIA686A_REG_ALARM2) << 8); | 
| 805 | data->last_updated = jiffies; | 732 | data->last_updated = jiffies; | 
| 806 | data->valid = 1; | 733 | data->valid = 1; | 
| 807 | } | 734 | } | 
| @@ -818,32 +745,102 @@ static struct pci_device_id via686a_pci_ids[] = { | |||
| 818 | 745 | ||
| 819 | MODULE_DEVICE_TABLE(pci, via686a_pci_ids); | 746 | MODULE_DEVICE_TABLE(pci, via686a_pci_ids); | 
| 820 | 747 | ||
| 748 | static int __devinit via686a_device_add(unsigned short address) | ||
| 749 | { | ||
| 750 | struct resource res = { | ||
| 751 | .start = address, | ||
| 752 | .end = address + VIA686A_EXTENT - 1, | ||
| 753 | .name = "via686a", | ||
| 754 | .flags = IORESOURCE_IO, | ||
| 755 | }; | ||
| 756 | int err; | ||
| 757 | |||
| 758 | pdev = platform_device_alloc("via686a", address); | ||
| 759 | if (!pdev) { | ||
| 760 | err = -ENOMEM; | ||
| 761 | printk(KERN_ERR "via686a: Device allocation failed\n"); | ||
| 762 | goto exit; | ||
| 763 | } | ||
| 764 | |||
| 765 | err = platform_device_add_resources(pdev, &res, 1); | ||
| 766 | if (err) { | ||
| 767 | printk(KERN_ERR "via686a: Device resource addition failed " | ||
| 768 | "(%d)\n", err); | ||
| 769 | goto exit_device_put; | ||
| 770 | } | ||
| 771 | |||
| 772 | err = platform_device_add(pdev); | ||
| 773 | if (err) { | ||
| 774 | printk(KERN_ERR "via686a: Device addition failed (%d)\n", | ||
| 775 | err); | ||
| 776 | goto exit_device_put; | ||
| 777 | } | ||
| 778 | |||
| 779 | return 0; | ||
| 780 | |||
| 781 | exit_device_put: | ||
| 782 | platform_device_put(pdev); | ||
| 783 | exit: | ||
| 784 | return err; | ||
| 785 | } | ||
| 786 | |||
| 821 | static int __devinit via686a_pci_probe(struct pci_dev *dev, | 787 | static int __devinit via686a_pci_probe(struct pci_dev *dev, | 
| 822 | const struct pci_device_id *id) | 788 | const struct pci_device_id *id) | 
| 823 | { | 789 | { | 
| 824 | u16 val; | 790 | u16 address, val; | 
| 825 | 791 | ||
| 792 | if (force_addr) { | ||
| 793 | address = force_addr & ~(VIA686A_EXTENT - 1); | ||
| 794 | dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address); | ||
| 795 | if (PCIBIOS_SUCCESSFUL != | ||
| 796 | pci_write_config_word(dev, VIA686A_BASE_REG, address | 1)) | ||
| 797 | return -ENODEV; | ||
| 798 | } | ||
| 826 | if (PCIBIOS_SUCCESSFUL != | 799 | if (PCIBIOS_SUCCESSFUL != | 
| 827 | pci_read_config_word(dev, VIA686A_BASE_REG, &val)) | 800 | pci_read_config_word(dev, VIA686A_BASE_REG, &val)) | 
| 828 | return -ENODEV; | 801 | return -ENODEV; | 
| 829 | 802 | ||
| 830 | address = val & ~(VIA686A_EXTENT - 1); | 803 | address = val & ~(VIA686A_EXTENT - 1); | 
| 831 | if (address == 0 && force_addr == 0) { | 804 | if (address == 0) { | 
| 832 | dev_err(&dev->dev, "base address not set - upgrade BIOS " | 805 | dev_err(&dev->dev, "base address not set - upgrade BIOS " | 
| 833 | "or use force_addr=0xaddr\n"); | 806 | "or use force_addr=0xaddr\n"); | 
| 834 | return -ENODEV; | 807 | return -ENODEV; | 
| 835 | } | 808 | } | 
| 836 | 809 | ||
| 837 | s_bridge = pci_dev_get(dev); | 810 | if (PCIBIOS_SUCCESSFUL != | 
| 838 | if (i2c_isa_add_driver(&via686a_driver)) { | 811 | pci_read_config_word(dev, VIA686A_ENABLE_REG, &val)) | 
| 839 | pci_dev_put(s_bridge); | 812 | return -ENODEV; | 
| 840 | s_bridge = NULL; | 813 | if (!(val & 0x0001)) { | 
| 814 | if (!force_addr) { | ||
| 815 | dev_warn(&dev->dev, "Sensors disabled, enable " | ||
| 816 | "with force_addr=0x%x\n", address); | ||
| 817 | return -ENODEV; | ||
| 818 | } | ||
| 819 | |||
| 820 | dev_warn(&dev->dev, "Enabling sensors\n"); | ||
| 821 | if (PCIBIOS_SUCCESSFUL != | ||
| 822 | pci_write_config_word(dev, VIA686A_ENABLE_REG, | ||
| 823 | val | 0x0001)) | ||
| 824 | return -ENODEV; | ||
| 841 | } | 825 | } | 
| 842 | 826 | ||
| 827 | if (platform_driver_register(&via686a_driver)) | ||
| 828 | goto exit; | ||
| 829 | |||
| 830 | /* Sets global pdev as a side effect */ | ||
| 831 | if (via686a_device_add(address)) | ||
| 832 | goto exit_unregister; | ||
| 833 | |||
| 843 | /* Always return failure here. This is to allow other drivers to bind | 834 | /* Always return failure here. This is to allow other drivers to bind | 
| 844 | * to this pci device. We don't really want to have control over the | 835 | * to this pci device. We don't really want to have control over the | 
| 845 | * pci device, we only wanted to read as few register values from it. | 836 | * pci device, we only wanted to read as few register values from it. | 
| 846 | */ | 837 | */ | 
| 838 | s_bridge = pci_dev_get(dev); | ||
| 839 | return -ENODEV; | ||
| 840 | |||
| 841 | exit_unregister: | ||
| 842 | platform_driver_unregister(&via686a_driver); | ||
| 843 | exit: | ||
| 847 | return -ENODEV; | 844 | return -ENODEV; | 
| 848 | } | 845 | } | 
| 849 | 846 | ||
| @@ -862,7 +859,8 @@ static void __exit sm_via686a_exit(void) | |||
| 862 | { | 859 | { | 
| 863 | pci_unregister_driver(&via686a_pci_driver); | 860 | pci_unregister_driver(&via686a_pci_driver); | 
| 864 | if (s_bridge != NULL) { | 861 | if (s_bridge != NULL) { | 
| 865 | i2c_isa_del_driver(&via686a_driver); | 862 | platform_device_unregister(pdev); | 
| 863 | platform_driver_unregister(&via686a_driver); | ||
| 866 | pci_dev_put(s_bridge); | 864 | pci_dev_put(s_bridge); | 
| 867 | s_bridge = NULL; | 865 | s_bridge = NULL; | 
| 868 | } | 866 | } | 
