aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/lm78.c
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 /drivers/hwmon/lm78.c
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>
Diffstat (limited to 'drivers/hwmon/lm78.c')
-rw-r--r--drivers/hwmon/lm78.c377
1 files changed, 267 insertions, 110 deletions
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