aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2007-05-08 11:22:00 -0400
committerJean Delvare <khali@hyperion.delvare>2007-05-08 11:22:00 -0400
commitc40769fee13c1ab43e1fb10320d6fbc29f582d8e (patch)
tree3537ff512e69e7ab7d86214edd85dcca3a2aea52
parentd20620de0c3de622a9d6a841725bafaed6d1aec2 (diff)
hwmon/lm78: No longer use i2c-isa
Reimplement the ISA device support as a platform driver, so that we no longer rely on i2c-isa. Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/lm78.c377
2 files changed, 267 insertions, 111 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d89bd5eb50ae..659a2abb3e90 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -291,7 +291,6 @@ config SENSORS_LM77
291config SENSORS_LM78 291config SENSORS_LM78
292 tristate "National Semiconductor LM78 and compatibles" 292 tristate "National Semiconductor LM78 and compatibles"
293 depends on HWMON && I2C 293 depends on HWMON && I2C
294 select I2C_ISA
295 select HWMON_VID 294 select HWMON_VID
296 help 295 help
297 If you say yes here you get support for National Semiconductor LM78, 296 If you say yes here you get support for National Semiconductor LM78,
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 886786c33916..cfb08978459d 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -2,6 +2,7 @@
2 lm78.c - Part of lm_sensors, Linux kernel modules for hardware 2 lm78.c - Part of lm_sensors, Linux kernel modules for hardware
3 monitoring 3 monitoring
4 Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> 4 Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
5 Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
5 6
6 This program is free software; you can redistribute it and/or modify 7 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 8 it under the terms of the GNU General Public License as published by
@@ -23,13 +24,17 @@
23#include <linux/slab.h> 24#include <linux/slab.h>
24#include <linux/jiffies.h> 25#include <linux/jiffies.h>
25#include <linux/i2c.h> 26#include <linux/i2c.h>
26#include <linux/i2c-isa.h> 27#include <linux/platform_device.h>
28#include <linux/ioport.h>
27#include <linux/hwmon.h> 29#include <linux/hwmon.h>
28#include <linux/hwmon-vid.h> 30#include <linux/hwmon-vid.h>
29#include <linux/err.h> 31#include <linux/err.h>
30#include <linux/mutex.h> 32#include <linux/mutex.h>
31#include <asm/io.h> 33#include <asm/io.h>
32 34
35/* ISA device, if found */
36static struct platform_device *pdev;
37
33/* Addresses to scan */ 38/* Addresses to scan */
34static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 39static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
35 0x25, 0x26, 0x27, 0x28, 0x29, 40 0x25, 0x26, 0x27, 0x28, 0x29,
@@ -121,12 +126,8 @@ static inline int TEMP_FROM_REG(s8 val)
121 a bit - except if there could be more than one SMBus. Groan. No solution 126 a bit - except if there could be more than one SMBus. Groan. No solution
122 for this yet. */ 127 for this yet. */
123 128
124/* This module may seem overly long and complicated. In fact, it is not so 129/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
125 bad. Quite a lot of bookkeeping is done. A real driver can often cut 130 the driver field to differentiate between I2C and ISA chips. */
126 some corners. */
127
128/* For each registered chip, we need to keep some data in memory.
129 The structure is dynamically allocated. */
130struct lm78_data { 131struct lm78_data {
131 struct i2c_client client; 132 struct i2c_client client;
132 struct class_device *class_dev; 133 struct class_device *class_dev;
@@ -152,10 +153,12 @@ struct lm78_data {
152 153
153 154
154static int lm78_attach_adapter(struct i2c_adapter *adapter); 155static int lm78_attach_adapter(struct i2c_adapter *adapter);
155static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
156static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); 156static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
157static int lm78_detach_client(struct i2c_client *client); 157static int lm78_detach_client(struct i2c_client *client);
158 158
159static int __devinit lm78_isa_probe(struct platform_device *pdev);
160static int __devexit lm78_isa_remove(struct platform_device *pdev);
161
159static int lm78_read_value(struct i2c_client *client, u8 reg); 162static int lm78_read_value(struct i2c_client *client, u8 reg);
160static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); 163static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value);
161static struct lm78_data *lm78_update_device(struct device *dev); 164static struct lm78_data *lm78_update_device(struct device *dev);
@@ -171,13 +174,13 @@ static struct i2c_driver lm78_driver = {
171 .detach_client = lm78_detach_client, 174 .detach_client = lm78_detach_client,
172}; 175};
173 176
174static struct i2c_driver lm78_isa_driver = { 177static struct platform_driver lm78_isa_driver = {
175 .driver = { 178 .driver = {
176 .owner = THIS_MODULE, 179 .owner = THIS_MODULE,
177 .name = "lm78-isa", 180 .name = "lm78",
178 }, 181 },
179 .attach_adapter = lm78_isa_attach_adapter, 182 .probe = lm78_isa_probe,
180 .detach_client = lm78_detach_client, 183 .remove = lm78_isa_remove,
181}; 184};
182 185
183 186
@@ -203,8 +206,8 @@ static ssize_t show_in_max(struct device *dev, char *buf, int nr)
203static ssize_t set_in_min(struct device *dev, const char *buf, 206static ssize_t set_in_min(struct device *dev, const char *buf,
204 size_t count, int nr) 207 size_t count, int nr)
205{ 208{
206 struct i2c_client *client = to_i2c_client(dev); 209 struct lm78_data *data = dev_get_drvdata(dev);
207 struct lm78_data *data = i2c_get_clientdata(client); 210 struct i2c_client *client = &data->client;
208 unsigned long val = simple_strtoul(buf, NULL, 10); 211 unsigned long val = simple_strtoul(buf, NULL, 10);
209 212
210 mutex_lock(&data->update_lock); 213 mutex_lock(&data->update_lock);
@@ -217,8 +220,8 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
217static ssize_t set_in_max(struct device *dev, const char *buf, 220static ssize_t set_in_max(struct device *dev, const char *buf,
218 size_t count, int nr) 221 size_t count, int nr)
219{ 222{
220 struct i2c_client *client = to_i2c_client(dev); 223 struct lm78_data *data = dev_get_drvdata(dev);
221 struct lm78_data *data = i2c_get_clientdata(client); 224 struct i2c_client *client = &data->client;
222 unsigned long val = simple_strtoul(buf, NULL, 10); 225 unsigned long val = simple_strtoul(buf, NULL, 10);
223 226
224 mutex_lock(&data->update_lock); 227 mutex_lock(&data->update_lock);
@@ -284,8 +287,8 @@ static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr,
284 287
285static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 288static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
286{ 289{
287 struct i2c_client *client = to_i2c_client(dev); 290 struct lm78_data *data = dev_get_drvdata(dev);
288 struct lm78_data *data = i2c_get_clientdata(client); 291 struct i2c_client *client = &data->client;
289 long val = simple_strtol(buf, NULL, 10); 292 long val = simple_strtol(buf, NULL, 10);
290 293
291 mutex_lock(&data->update_lock); 294 mutex_lock(&data->update_lock);
@@ -303,8 +306,8 @@ static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr,
303 306
304static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 307static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
305{ 308{
306 struct i2c_client *client = to_i2c_client(dev); 309 struct lm78_data *data = dev_get_drvdata(dev);
307 struct lm78_data *data = i2c_get_clientdata(client); 310 struct i2c_client *client = &data->client;
308 long val = simple_strtol(buf, NULL, 10); 311 long val = simple_strtol(buf, NULL, 10);
309 312
310 mutex_lock(&data->update_lock); 313 mutex_lock(&data->update_lock);
@@ -338,8 +341,8 @@ static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
338static ssize_t set_fan_min(struct device *dev, const char *buf, 341static ssize_t set_fan_min(struct device *dev, const char *buf,
339 size_t count, int nr) 342 size_t count, int nr)
340{ 343{
341 struct i2c_client *client = to_i2c_client(dev); 344 struct lm78_data *data = dev_get_drvdata(dev);
342 struct lm78_data *data = i2c_get_clientdata(client); 345 struct i2c_client *client = &data->client;
343 unsigned long val = simple_strtoul(buf, NULL, 10); 346 unsigned long val = simple_strtoul(buf, NULL, 10);
344 347
345 mutex_lock(&data->update_lock); 348 mutex_lock(&data->update_lock);
@@ -362,8 +365,8 @@ static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
362static ssize_t set_fan_div(struct device *dev, const char *buf, 365static ssize_t set_fan_div(struct device *dev, const char *buf,
363 size_t count, int nr) 366 size_t count, int nr)
364{ 367{
365 struct i2c_client *client = to_i2c_client(dev); 368 struct lm78_data *data = dev_get_drvdata(dev);
366 struct lm78_data *data = i2c_get_clientdata(client); 369 struct i2c_client *client = &data->client;
367 unsigned long val = simple_strtoul(buf, NULL, 10); 370 unsigned long val = simple_strtoul(buf, NULL, 10);
368 unsigned long min; 371 unsigned long min;
369 u8 reg; 372 u8 reg;
@@ -378,7 +381,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
378 case 4: data->fan_div[nr] = 2; break; 381 case 4: data->fan_div[nr] = 2; break;
379 case 8: data->fan_div[nr] = 3; break; 382 case 8: data->fan_div[nr] = 3; break;
380 default: 383 default:
381 dev_err(&client->dev, "fan_div value %ld not " 384 dev_err(dev, "fan_div value %ld not "
382 "supported. Choose one of 1, 2, 4 or 8!\n", val); 385 "supported. Choose one of 1, 2, 4 or 8!\n", val);
383 mutex_unlock(&data->update_lock); 386 mutex_unlock(&data->update_lock);
384 return -EINVAL; 387 return -EINVAL;
@@ -475,11 +478,6 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
475 return i2c_probe(adapter, &addr_data, lm78_detect); 478 return i2c_probe(adapter, &addr_data, lm78_detect);
476} 479}
477 480
478static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
479{
480 return lm78_detect(adapter, isa_address, -1);
481}
482
483static struct attribute *lm78_attributes[] = { 481static struct attribute *lm78_attributes[] = {
484 &dev_attr_in0_input.attr, 482 &dev_attr_in0_input.attr,
485 &dev_attr_in0_min.attr, 483 &dev_attr_in0_min.attr,
@@ -524,6 +522,17 @@ static const struct attribute_group lm78_group = {
524 .attrs = lm78_attributes, 522 .attrs = lm78_attributes,
525}; 523};
526 524
525/* I2C devices get this name attribute automatically, but for ISA devices
526 we must create it by ourselves. */
527static ssize_t show_name(struct device *dev, struct device_attribute
528 *devattr, char *buf)
529{
530 struct lm78_data *data = dev_get_drvdata(dev);
531
532 return sprintf(buf, "%s\n", data->client.name);
533}
534static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
535
527/* This function is called by i2c_probe */ 536/* This function is called by i2c_probe */
528static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) 537static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
529{ 538{
@@ -531,54 +540,10 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
531 struct i2c_client *new_client; 540 struct i2c_client *new_client;
532 struct lm78_data *data; 541 struct lm78_data *data;
533 const char *client_name = ""; 542 const char *client_name = "";
534 int is_isa = i2c_is_isa_adapter(adapter);
535 543
536 if (!is_isa && 544 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
537 !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
538 err = -ENODEV; 545 err = -ENODEV;
539 goto ERROR0; 546 goto ERROR1;
540 }
541
542 /* Reserve the ISA region */
543 if (is_isa)
544 if (!request_region(address, LM78_EXTENT,
545 lm78_isa_driver.driver.name)) {
546 err = -EBUSY;
547 goto ERROR0;
548 }
549
550 /* Probe whether there is anything available on this address. Already
551 done for SMBus clients */
552 if (kind < 0) {
553 if (is_isa) {
554
555#define REALLY_SLOW_IO
556 /* We need the timeouts for at least some LM78-like
557 chips. But only if we read 'undefined' registers. */
558 i = inb_p(address + 1);
559 if (inb_p(address + 2) != i) {
560 err = -ENODEV;
561 goto ERROR1;
562 }
563 if (inb_p(address + 3) != i) {
564 err = -ENODEV;
565 goto ERROR1;
566 }
567 if (inb_p(address + 7) != i) {
568 err = -ENODEV;
569 goto ERROR1;
570 }
571#undef REALLY_SLOW_IO
572
573 /* Let's just hope nothing breaks here */
574 i = inb_p(address + 5) & 0x7f;
575 outb_p(~i & 0x7f, address + 5);
576 if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
577 outb_p(i, address + 5);
578 err = -ENODEV;
579 goto ERROR1;
580 }
581 }
582 } 547 }
583 548
584 /* OK. For now, we presume we have a valid client. We now create the 549 /* OK. For now, we presume we have a valid client. We now create the
@@ -591,13 +556,10 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
591 } 556 }
592 557
593 new_client = &data->client; 558 new_client = &data->client;
594 if (is_isa)
595 mutex_init(&data->lock);
596 i2c_set_clientdata(new_client, data); 559 i2c_set_clientdata(new_client, data);
597 new_client->addr = address; 560 new_client->addr = address;
598 new_client->adapter = adapter; 561 new_client->adapter = adapter;
599 new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver; 562 new_client->driver = &lm78_driver;
600 new_client->flags = 0;
601 563
602 /* Now, we do the remaining detection. */ 564 /* Now, we do the remaining detection. */
603 if (kind < 0) { 565 if (kind < 0) {
@@ -605,8 +567,8 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
605 err = -ENODEV; 567 err = -ENODEV;
606 goto ERROR2; 568 goto ERROR2;
607 } 569 }
608 if (!is_isa && (lm78_read_value( 570 if (lm78_read_value(new_client, LM78_REG_I2C_ADDR) !=
609 new_client, LM78_REG_I2C_ADDR) != address)) { 571 address) {
610 err = -ENODEV; 572 err = -ENODEV;
611 goto ERROR2; 573 goto ERROR2;
612 } 574 }
@@ -641,9 +603,6 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
641 strlcpy(new_client->name, client_name, I2C_NAME_SIZE); 603 strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
642 data->type = kind; 604 data->type = kind;
643 605
644 data->valid = 0;
645 mutex_init(&data->update_lock);
646
647 /* Tell the I2C layer a new client has arrived */ 606 /* Tell the I2C layer a new client has arrived */
648 if ((err = i2c_attach_client(new_client))) 607 if ((err = i2c_attach_client(new_client)))
649 goto ERROR2; 608 goto ERROR2;
@@ -651,12 +610,6 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
651 /* Initialize the LM78 chip */ 610 /* Initialize the LM78 chip */
652 lm78_init_client(new_client); 611 lm78_init_client(new_client);
653 612
654 /* A few vars need to be filled upon startup */
655 for (i = 0; i < 3; i++) {
656 data->fan_min[i] = lm78_read_value(new_client,
657 LM78_REG_FAN_MIN(i));
658 }
659
660 /* Register sysfs hooks */ 613 /* Register sysfs hooks */
661 if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) 614 if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group)))
662 goto ERROR3; 615 goto ERROR3;
@@ -676,9 +629,6 @@ ERROR3:
676ERROR2: 629ERROR2:
677 kfree(data); 630 kfree(data);
678ERROR1: 631ERROR1:
679 if (is_isa)
680 release_region(address, LM78_EXTENT);
681ERROR0:
682 return err; 632 return err;
683} 633}
684 634
@@ -693,9 +643,77 @@ static int lm78_detach_client(struct i2c_client *client)
693 if ((err = i2c_detach_client(client))) 643 if ((err = i2c_detach_client(client)))
694 return err; 644 return err;
695 645
696 if(i2c_is_isa_client(client)) 646 kfree(data);
697 release_region(client->addr, LM78_EXTENT); 647
648 return 0;
649}
650
651static int __devinit lm78_isa_probe(struct platform_device *pdev)
652{
653 int err;
654 struct lm78_data *data;
655 struct resource *res;
656 const char *name;
657
658 /* Reserve the ISA region */
659 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
660 if (!request_region(res->start, LM78_EXTENT, "lm78")) {
661 err = -EBUSY;
662 goto exit;
663 }
664
665 if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
666 err = -ENOMEM;
667 goto exit_release_region;
668 }
669 mutex_init(&data->lock);
670 data->client.addr = res->start;
671 i2c_set_clientdata(&data->client, data);
672 platform_set_drvdata(pdev, data);
673
674 if (lm78_read_value(&data->client, LM78_REG_CHIPID) & 0x80) {
675 data->type = lm79;
676 name = "lm79";
677 } else {
678 data->type = lm78;
679 name = "lm78";
680 }
681 strlcpy(data->client.name, name, I2C_NAME_SIZE);
682
683 /* Initialize the LM78 chip */
684 lm78_init_client(&data->client);
685
686 /* Register sysfs hooks */
687 if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
688 || (err = device_create_file(&pdev->dev, &dev_attr_name)))
689 goto exit_remove_files;
690
691 data->class_dev = hwmon_device_register(&pdev->dev);
692 if (IS_ERR(data->class_dev)) {
693 err = PTR_ERR(data->class_dev);
694 goto exit_remove_files;
695 }
696
697 return 0;
698
699 exit_remove_files:
700 sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
701 device_remove_file(&pdev->dev, &dev_attr_name);
702 kfree(data);
703 exit_release_region:
704 release_region(res->start, LM78_EXTENT);
705 exit:
706 return err;
707}
708
709static int __devexit lm78_isa_remove(struct platform_device *pdev)
710{
711 struct lm78_data *data = platform_get_drvdata(pdev);
698 712
713 hwmon_device_unregister(data->class_dev);
714 sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
715 device_remove_file(&pdev->dev, &dev_attr_name);
716 release_region(data->client.addr, LM78_EXTENT);
699 kfree(data); 717 kfree(data);
700 718
701 return 0; 719 return 0;
@@ -709,7 +727,7 @@ static int lm78_detach_client(struct i2c_client *client)
709static int lm78_read_value(struct i2c_client *client, u8 reg) 727static int lm78_read_value(struct i2c_client *client, u8 reg)
710{ 728{
711 int res; 729 int res;
712 if (i2c_is_isa_client(client)) { 730 if (!client->driver) { /* ISA device */
713 struct lm78_data *data = i2c_get_clientdata(client); 731 struct lm78_data *data = i2c_get_clientdata(client);
714 mutex_lock(&data->lock); 732 mutex_lock(&data->lock);
715 outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); 733 outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
@@ -729,7 +747,7 @@ static int lm78_read_value(struct i2c_client *client, u8 reg)
729 nowhere else be necessary! */ 747 nowhere else be necessary! */
730static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) 748static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
731{ 749{
732 if (i2c_is_isa_client(client)) { 750 if (!client->driver) { /* ISA device */
733 struct lm78_data *data = i2c_get_clientdata(client); 751 struct lm78_data *data = i2c_get_clientdata(client);
734 mutex_lock(&data->lock); 752 mutex_lock(&data->lock);
735 outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); 753 outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET);
@@ -742,18 +760,29 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
742 760
743static void lm78_init_client(struct i2c_client *client) 761static void lm78_init_client(struct i2c_client *client)
744{ 762{
745 u8 config = lm78_read_value(client, LM78_REG_CONFIG); 763 struct lm78_data *data = i2c_get_clientdata(client);
764 u8 config;
765 int i;
746 766
747 /* Start monitoring */ 767 /* Start monitoring */
748 if (!(config & 0x01)) 768 config = lm78_read_value(client, LM78_REG_CONFIG);
769 if ((config & 0x09) != 0x01)
749 lm78_write_value(client, LM78_REG_CONFIG, 770 lm78_write_value(client, LM78_REG_CONFIG,
750 (config & 0xf7) | 0x01); 771 (config & 0xf7) | 0x01);
772
773 /* A few vars need to be filled upon startup */
774 for (i = 0; i < 3; i++) {
775 data->fan_min[i] = lm78_read_value(client,
776 LM78_REG_FAN_MIN(i));
777 }
778
779 mutex_init(&data->update_lock);
751} 780}
752 781
753static struct lm78_data *lm78_update_device(struct device *dev) 782static struct lm78_data *lm78_update_device(struct device *dev)
754{ 783{
755 struct i2c_client *client = to_i2c_client(dev); 784 struct lm78_data *data = dev_get_drvdata(dev);
756 struct lm78_data *data = i2c_get_clientdata(client); 785 struct i2c_client *client = &data->client;
757 int i; 786 int i;
758 787
759 mutex_lock(&data->update_lock); 788 mutex_lock(&data->update_lock);
@@ -761,7 +790,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
761 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 790 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
762 || !data->valid) { 791 || !data->valid) {
763 792
764 dev_dbg(&client->dev, "Starting lm78 update\n"); 793 dev_dbg(dev, "Starting lm78 update\n");
765 794
766 for (i = 0; i <= 6; i++) { 795 for (i = 0; i <= 6; i++) {
767 data->in[i] = 796 data->in[i] =
@@ -805,26 +834,154 @@ static struct lm78_data *lm78_update_device(struct device *dev)
805 return data; 834 return data;
806} 835}
807 836
837/* return 1 if a supported chip is found, 0 otherwise */
838static int __init lm78_isa_found(unsigned short address)
839{
840 int val, save, found = 0;
841
842 if (!request_region(address, LM78_EXTENT, "lm78"))
843 return 0;
844
845#define REALLY_SLOW_IO
846 /* We need the timeouts for at least some LM78-like
847 chips. But only if we read 'undefined' registers. */
848 val = inb_p(address + 1);
849 if (inb_p(address + 2) != val
850 || inb_p(address + 3) != val
851 || inb_p(address + 7) != val)
852 goto release;
853#undef REALLY_SLOW_IO
854
855 /* We should be able to change the 7 LSB of the address port. The
856 MSB (busy flag) should be clear initially, set after the write. */
857 save = inb_p(address + LM78_ADDR_REG_OFFSET);
858 if (save & 0x80)
859 goto release;
860 val = ~save & 0x7f;
861 outb_p(val, address + LM78_ADDR_REG_OFFSET);
862 if (inb_p(address + LM78_ADDR_REG_OFFSET) != (val | 0x80)) {
863 outb_p(save, address + LM78_ADDR_REG_OFFSET);
864 goto release;
865 }
866
867 /* We found a device, now see if it could be an LM78 */
868 outb_p(LM78_REG_CONFIG, address + LM78_ADDR_REG_OFFSET);
869 val = inb_p(address + LM78_DATA_REG_OFFSET);
870 if (val & 0x80)
871 goto release;
872 outb_p(LM78_REG_I2C_ADDR, address + LM78_ADDR_REG_OFFSET);
873 val = inb_p(address + LM78_DATA_REG_OFFSET);
874 if (val < 0x03 || val > 0x77) /* Not a valid I2C address */
875 goto release;
876
877 /* The busy flag should be clear again */
878 if (inb_p(address + LM78_ADDR_REG_OFFSET) & 0x80)
879 goto release;
880
881 /* Explicitly prevent the misdetection of Winbond chips */
882 outb_p(0x4f, address + LM78_ADDR_REG_OFFSET);
883 val = inb_p(address + LM78_DATA_REG_OFFSET);
884 if (val == 0xa3 || val == 0x5c)
885 goto release;
886
887 /* Explicitly prevent the misdetection of ITE chips */
888 outb_p(0x58, address + LM78_ADDR_REG_OFFSET);
889 val = inb_p(address + LM78_DATA_REG_OFFSET);
890 if (val == 0x90)
891 goto release;
892
893 /* Determine the chip type */
894 outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET);
895 val = inb_p(address + LM78_DATA_REG_OFFSET);
896 if (val == 0x00 /* LM78 */
897 || val == 0x40 /* LM78-J */
898 || (val & 0xfe) == 0xc0) /* LM79 */
899 found = 1;
900
901 if (found)
902 pr_info("lm78: Found an %s chip at %#x\n",
903 val & 0x80 ? "LM79" : "LM78", (int)address);
904
905 release:
906 release_region(address, LM78_EXTENT);
907 return found;
908}
909
910static int __init lm78_isa_device_add(unsigned short address)
911{
912 struct resource res = {
913 .start = address,
914 .end = address + LM78_EXTENT,
915 .name = "lm78",
916 .flags = IORESOURCE_IO,
917 };
918 int err;
919
920 pdev = platform_device_alloc("lm78", address);
921 if (!pdev) {
922 err = -ENOMEM;
923 printk(KERN_ERR "lm78: Device allocation failed\n");
924 goto exit;
925 }
926
927 err = platform_device_add_resources(pdev, &res, 1);
928 if (err) {
929 printk(KERN_ERR "lm78: Device resource addition failed "
930 "(%d)\n", err);
931 goto exit_device_put;
932 }
933
934 err = platform_device_add(pdev);
935 if (err) {
936 printk(KERN_ERR "lm78: Device addition failed (%d)\n",
937 err);
938 goto exit_device_put;
939 }
940
941 return 0;
942
943 exit_device_put:
944 platform_device_put(pdev);
945 exit:
946 pdev = NULL;
947 return err;
948}
949
808static int __init sm_lm78_init(void) 950static int __init sm_lm78_init(void)
809{ 951{
810 int res; 952 int res;
811 953
812 res = i2c_add_driver(&lm78_driver); 954 res = i2c_add_driver(&lm78_driver);
813 if (res) 955 if (res)
814 return res; 956 goto exit;
957
958 if (lm78_isa_found(isa_address)) {
959 res = platform_driver_register(&lm78_isa_driver);
960 if (res)
961 goto exit_unreg_i2c_driver;
815 962
816 /* Don't exit if this one fails, we still want the I2C variants 963 /* Sets global pdev as a side effect */
817 to work! */ 964 res = lm78_isa_device_add(isa_address);
818 if (i2c_isa_add_driver(&lm78_isa_driver)) 965 if (res)
819 isa_address = 0; 966 goto exit_unreg_isa_driver;
967 }
820 968
821 return 0; 969 return 0;
970
971 exit_unreg_isa_driver:
972 platform_driver_unregister(&lm78_isa_driver);
973 exit_unreg_i2c_driver:
974 i2c_del_driver(&lm78_driver);
975 exit:
976 return res;
822} 977}
823 978
824static void __exit sm_lm78_exit(void) 979static void __exit sm_lm78_exit(void)
825{ 980{
826 if (isa_address) 981 if (pdev) {
827 i2c_isa_del_driver(&lm78_isa_driver); 982 platform_device_unregister(pdev);
983 platform_driver_unregister(&lm78_isa_driver);
984 }
828 i2c_del_driver(&lm78_driver); 985 i2c_del_driver(&lm78_driver);
829} 986}
830 987