aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/lm78.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/lm78.c')
-rw-r--r--drivers/hwmon/lm78.c84
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 };
34static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END }; 37static unsigned short isa_address = 0x290;
35 38
36/* Insmod parameters */ 39/* Insmod parameters */
37SENSORS_INSMOD_3(lm78, lm78j, lm79); 40I2C_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) */
109static 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. */
135struct lm78_data { 131struct 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
158static int lm78_attach_adapter(struct i2c_adapter *adapter); 155static int lm78_attach_adapter(struct i2c_adapter *adapter);
156static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
159static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); 157static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
160static int lm78_detach_client(struct i2c_client *client); 158static 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
175static 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 */
178static ssize_t show_in(struct device *dev, char *buf, int nr) 184static 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);
445static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) 451static 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}
450static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); 456static 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
477static 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 */
472int lm78_detect(struct i2c_adapter *adapter, int address, int kind) 483int 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
661ERROR3:
662 i2c_detach_client(new_client);
646ERROR2: 663ERROR2:
647 kfree(data); 664 kfree(data);
648ERROR1: 665ERROR1:
@@ -654,18 +671,18 @@ ERROR0:
654 671
655static int lm78_detach_client(struct i2c_client *client) 672static 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
778static int __init sm_lm78_init(void) 795static 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
783static void __exit sm_lm78_exit(void) 812static 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
790MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); 820MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
791MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver"); 821MODULE_DESCRIPTION("LM78/LM79 driver");
792MODULE_LICENSE("GPL"); 822MODULE_LICENSE("GPL");
793 823
794module_init(sm_lm78_init); 824module_init(sm_lm78_init);