diff options
Diffstat (limited to 'drivers/hwmon/lm78.c')
-rw-r--r-- | drivers/hwmon/lm78.c | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 29241469dcba..f6730dc3573b 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
@@ -23,7 +23,10 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/jiffies.h> | 24 | #include <linux/jiffies.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/i2c-sensor.h> | 26 | #include <linux/i2c-isa.h> |
27 | #include <linux/hwmon.h> | ||
28 | #include <linux/hwmon-vid.h> | ||
29 | #include <linux/err.h> | ||
27 | #include <asm/io.h> | 30 | #include <asm/io.h> |
28 | 31 | ||
29 | /* Addresses to scan */ | 32 | /* Addresses to scan */ |
@@ -31,10 +34,10 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, | |||
31 | 0x25, 0x26, 0x27, 0x28, 0x29, | 34 | 0x25, 0x26, 0x27, 0x28, 0x29, |
32 | 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, | 35 | 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, |
33 | 0x2f, I2C_CLIENT_END }; | 36 | 0x2f, I2C_CLIENT_END }; |
34 | static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END }; | 37 | static unsigned short isa_address = 0x290; |
35 | 38 | ||
36 | /* Insmod parameters */ | 39 | /* Insmod parameters */ |
37 | SENSORS_INSMOD_3(lm78, lm78j, lm79); | 40 | I2C_CLIENT_INSMOD_2(lm78, lm79); |
38 | 41 | ||
39 | /* Many LM78 constants specified below */ | 42 | /* Many LM78 constants specified below */ |
40 | 43 | ||
@@ -104,13 +107,6 @@ static inline int TEMP_FROM_REG(s8 val) | |||
104 | return val * 1000; | 107 | return val * 1000; |
105 | } | 108 | } |
106 | 109 | ||
107 | /* VID: mV | ||
108 | REG: (see doc/vid) */ | ||
109 | static inline int VID_FROM_REG(u8 val) | ||
110 | { | ||
111 | return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50; | ||
112 | } | ||
113 | |||
114 | #define DIV_FROM_REG(val) (1 << (val)) | 110 | #define DIV_FROM_REG(val) (1 << (val)) |
115 | 111 | ||
116 | /* There are some complications in a module like this. First off, LM78 chips | 112 | /* There are some complications in a module like this. First off, LM78 chips |
@@ -134,6 +130,7 @@ static inline int VID_FROM_REG(u8 val) | |||
134 | allocated. */ | 130 | allocated. */ |
135 | struct lm78_data { | 131 | struct lm78_data { |
136 | struct i2c_client client; | 132 | struct i2c_client client; |
133 | struct class_device *class_dev; | ||
137 | struct semaphore lock; | 134 | struct semaphore lock; |
138 | enum chips type; | 135 | enum chips type; |
139 | 136 | ||
@@ -156,6 +153,7 @@ struct lm78_data { | |||
156 | 153 | ||
157 | 154 | ||
158 | static int lm78_attach_adapter(struct i2c_adapter *adapter); | 155 | static int lm78_attach_adapter(struct i2c_adapter *adapter); |
156 | static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); | ||
159 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); | 157 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); |
160 | static int lm78_detach_client(struct i2c_client *client); | 158 | static int lm78_detach_client(struct i2c_client *client); |
161 | 159 | ||
@@ -174,6 +172,14 @@ static struct i2c_driver lm78_driver = { | |||
174 | .detach_client = lm78_detach_client, | 172 | .detach_client = lm78_detach_client, |
175 | }; | 173 | }; |
176 | 174 | ||
175 | static struct i2c_driver lm78_isa_driver = { | ||
176 | .owner = THIS_MODULE, | ||
177 | .name = "lm78-isa", | ||
178 | .attach_adapter = lm78_isa_attach_adapter, | ||
179 | .detach_client = lm78_detach_client, | ||
180 | }; | ||
181 | |||
182 | |||
177 | /* 7 Voltages */ | 183 | /* 7 Voltages */ |
178 | static ssize_t show_in(struct device *dev, char *buf, int nr) | 184 | static ssize_t show_in(struct device *dev, char *buf, int nr) |
179 | { | 185 | { |
@@ -445,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL); | |||
445 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) | 451 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) |
446 | { | 452 | { |
447 | struct lm78_data *data = lm78_update_device(dev); | 453 | struct lm78_data *data = lm78_update_device(dev); |
448 | return sprintf(buf, "%d\n", VID_FROM_REG(data->vid)); | 454 | return sprintf(buf, "%d\n", vid_from_reg(82, data->vid)); |
449 | } | 455 | } |
450 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 456 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
451 | 457 | ||
@@ -465,10 +471,15 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter) | |||
465 | { | 471 | { |
466 | if (!(adapter->class & I2C_CLASS_HWMON)) | 472 | if (!(adapter->class & I2C_CLASS_HWMON)) |
467 | return 0; | 473 | return 0; |
468 | return i2c_detect(adapter, &addr_data, lm78_detect); | 474 | return i2c_probe(adapter, &addr_data, lm78_detect); |
475 | } | ||
476 | |||
477 | static int lm78_isa_attach_adapter(struct i2c_adapter *adapter) | ||
478 | { | ||
479 | return lm78_detect(adapter, isa_address, -1); | ||
469 | } | 480 | } |
470 | 481 | ||
471 | /* This function is called by i2c_detect */ | 482 | /* This function is called by i2c_probe */ |
472 | int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | 483 | int lm78_detect(struct i2c_adapter *adapter, int address, int kind) |
473 | { | 484 | { |
474 | int i, err; | 485 | int i, err; |
@@ -485,7 +496,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
485 | 496 | ||
486 | /* Reserve the ISA region */ | 497 | /* Reserve the ISA region */ |
487 | if (is_isa) | 498 | if (is_isa) |
488 | if (!request_region(address, LM78_EXTENT, lm78_driver.name)) { | 499 | if (!request_region(address, LM78_EXTENT, |
500 | lm78_isa_driver.name)) { | ||
489 | err = -EBUSY; | 501 | err = -EBUSY; |
490 | goto ERROR0; | 502 | goto ERROR0; |
491 | } | 503 | } |
@@ -540,7 +552,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
540 | i2c_set_clientdata(new_client, data); | 552 | i2c_set_clientdata(new_client, data); |
541 | new_client->addr = address; | 553 | new_client->addr = address; |
542 | new_client->adapter = adapter; | 554 | new_client->adapter = adapter; |
543 | new_client->driver = &lm78_driver; | 555 | new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver; |
544 | new_client->flags = 0; | 556 | new_client->flags = 0; |
545 | 557 | ||
546 | /* Now, we do the remaining detection. */ | 558 | /* Now, we do the remaining detection. */ |
@@ -559,10 +571,9 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
559 | /* Determine the chip type. */ | 571 | /* Determine the chip type. */ |
560 | if (kind <= 0) { | 572 | if (kind <= 0) { |
561 | i = lm78_read_value(new_client, LM78_REG_CHIPID); | 573 | i = lm78_read_value(new_client, LM78_REG_CHIPID); |
562 | if (i == 0x00 || i == 0x20) | 574 | if (i == 0x00 || i == 0x20 /* LM78 */ |
575 | || i == 0x40) /* LM78-J */ | ||
563 | kind = lm78; | 576 | kind = lm78; |
564 | else if (i == 0x40) | ||
565 | kind = lm78j; | ||
566 | else if ((i & 0xfe) == 0xc0) | 577 | else if ((i & 0xfe) == 0xc0) |
567 | kind = lm79; | 578 | kind = lm79; |
568 | else { | 579 | else { |
@@ -578,8 +589,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
578 | 589 | ||
579 | if (kind == lm78) { | 590 | if (kind == lm78) { |
580 | client_name = "lm78"; | 591 | client_name = "lm78"; |
581 | } else if (kind == lm78j) { | ||
582 | client_name = "lm78-j"; | ||
583 | } else if (kind == lm79) { | 592 | } else if (kind == lm79) { |
584 | client_name = "lm79"; | 593 | client_name = "lm79"; |
585 | } | 594 | } |
@@ -605,6 +614,12 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
605 | } | 614 | } |
606 | 615 | ||
607 | /* Register sysfs hooks */ | 616 | /* Register sysfs hooks */ |
617 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
618 | if (IS_ERR(data->class_dev)) { | ||
619 | err = PTR_ERR(data->class_dev); | ||
620 | goto ERROR3; | ||
621 | } | ||
622 | |||
608 | device_create_file(&new_client->dev, &dev_attr_in0_input); | 623 | device_create_file(&new_client->dev, &dev_attr_in0_input); |
609 | device_create_file(&new_client->dev, &dev_attr_in0_min); | 624 | device_create_file(&new_client->dev, &dev_attr_in0_min); |
610 | device_create_file(&new_client->dev, &dev_attr_in0_max); | 625 | device_create_file(&new_client->dev, &dev_attr_in0_max); |
@@ -643,6 +658,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
643 | 658 | ||
644 | return 0; | 659 | return 0; |
645 | 660 | ||
661 | ERROR3: | ||
662 | i2c_detach_client(new_client); | ||
646 | ERROR2: | 663 | ERROR2: |
647 | kfree(data); | 664 | kfree(data); |
648 | ERROR1: | 665 | ERROR1: |
@@ -654,18 +671,18 @@ ERROR0: | |||
654 | 671 | ||
655 | static int lm78_detach_client(struct i2c_client *client) | 672 | static int lm78_detach_client(struct i2c_client *client) |
656 | { | 673 | { |
674 | struct lm78_data *data = i2c_get_clientdata(client); | ||
657 | int err; | 675 | int err; |
658 | 676 | ||
659 | if ((err = i2c_detach_client(client))) { | 677 | hwmon_device_unregister(data->class_dev); |
660 | dev_err(&client->dev, | 678 | |
661 | "Client deregistration failed, client not detached.\n"); | 679 | if ((err = i2c_detach_client(client))) |
662 | return err; | 680 | return err; |
663 | } | ||
664 | 681 | ||
665 | if(i2c_is_isa_client(client)) | 682 | if(i2c_is_isa_client(client)) |
666 | release_region(client->addr, LM78_EXTENT); | 683 | release_region(client->addr, LM78_EXTENT); |
667 | 684 | ||
668 | kfree(i2c_get_clientdata(client)); | 685 | kfree(data); |
669 | 686 | ||
670 | return 0; | 687 | return 0; |
671 | } | 688 | } |
@@ -777,18 +794,31 @@ static struct lm78_data *lm78_update_device(struct device *dev) | |||
777 | 794 | ||
778 | static int __init sm_lm78_init(void) | 795 | static int __init sm_lm78_init(void) |
779 | { | 796 | { |
780 | return i2c_add_driver(&lm78_driver); | 797 | int res; |
798 | |||
799 | res = i2c_add_driver(&lm78_driver); | ||
800 | if (res) | ||
801 | return res; | ||
802 | |||
803 | res = i2c_isa_add_driver(&lm78_isa_driver); | ||
804 | if (res) { | ||
805 | i2c_del_driver(&lm78_driver); | ||
806 | return res; | ||
807 | } | ||
808 | |||
809 | return 0; | ||
781 | } | 810 | } |
782 | 811 | ||
783 | static void __exit sm_lm78_exit(void) | 812 | static void __exit sm_lm78_exit(void) |
784 | { | 813 | { |
814 | i2c_isa_del_driver(&lm78_isa_driver); | ||
785 | i2c_del_driver(&lm78_driver); | 815 | i2c_del_driver(&lm78_driver); |
786 | } | 816 | } |
787 | 817 | ||
788 | 818 | ||
789 | 819 | ||
790 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); | 820 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); |
791 | MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver"); | 821 | MODULE_DESCRIPTION("LM78/LM79 driver"); |
792 | MODULE_LICENSE("GPL"); | 822 | MODULE_LICENSE("GPL"); |
793 | 823 | ||
794 | module_init(sm_lm78_init); | 824 | module_init(sm_lm78_init); |