[PATCH] new toplevel target: headers_check_all
[wrt350n-kernel.git] / drivers / i2c / busses / i2c-isa.c
blob5f33bc9c1e02ba7c134121c5beb8880c51f79eb3
1 /*
2 i2c-isa.c - an i2c-core-like thing for ISA hardware monitoring chips
3 Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
5 Based on the i2c-isa pseudo-adapter from the lm_sensors project
6 Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* This implements an i2c-core-like thing for ISA hardware monitoring
24 chips. Such chips are linked to the i2c subsystem for historical
25 reasons (because the early ISA hardware monitoring chips such as the
26 LM78 had both an I2C and an ISA interface). They used to be
27 registered with the main i2c-core, but as a first step in the
28 direction of a clean separation between I2C and ISA chip drivers,
29 we now have this separate core for ISA ones. It is significantly
30 more simple than the real one, of course, because we don't have to
31 handle multiple busses: there is only one (fake) ISA adapter.
32 It is worth noting that we still rely on i2c-core for some things
33 at the moment - but hopefully this won't last. */
35 #include <linux/init.h>
36 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/errno.h>
39 #include <linux/i2c.h>
40 #include <linux/i2c-isa.h>
41 #include <linux/platform_device.h>
42 #include <linux/completion.h>
44 static u32 isa_func(struct i2c_adapter *adapter);
46 /* This is the actual algorithm we define */
47 static const struct i2c_algorithm isa_algorithm = {
48 .functionality = isa_func,
51 /* There can only be one... */
52 static struct i2c_adapter isa_adapter = {
53 .owner = THIS_MODULE,
54 .id = I2C_HW_ISA,
55 .class = I2C_CLASS_HWMON,
56 .algo = &isa_algorithm,
57 .name = "ISA main adapter",
60 /* We can't do a thing... */
61 static u32 isa_func(struct i2c_adapter *adapter)
63 return 0;
67 /* Copied from i2c-core */
68 static ssize_t show_adapter_name(struct device *dev,
69 struct device_attribute *attr, char *buf)
71 struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
72 return sprintf(buf, "%s\n", adap->name);
74 static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
77 /* We implement an interface which resembles i2c_{add,del}_driver,
78 but for i2c-isa drivers. We don't have to remember and handle lists
79 of drivers and adapters so this is much more simple, of course. */
81 int i2c_isa_add_driver(struct i2c_driver *driver)
83 int res;
85 /* Add the driver to the list of i2c drivers in the driver core */
86 driver->driver.bus = &i2c_bus_type;
87 res = driver_register(&driver->driver);
88 if (res)
89 return res;
90 dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
92 /* Now look for clients */
93 res = driver->attach_adapter(&isa_adapter);
94 if (res) {
95 dev_dbg(&isa_adapter.dev,
96 "Driver %s failed to attach adapter, unregistering\n",
97 driver->driver.name);
98 driver_unregister(&driver->driver);
100 return res;
103 int i2c_isa_del_driver(struct i2c_driver *driver)
105 struct list_head *item, *_n;
106 struct i2c_client *client;
107 int res;
109 /* Detach all clients belonging to this one driver */
110 list_for_each_safe(item, _n, &isa_adapter.clients) {
111 client = list_entry(item, struct i2c_client, list);
112 if (client->driver != driver)
113 continue;
114 dev_dbg(&isa_adapter.dev, "Detaching client %s at 0x%x\n",
115 client->name, client->addr);
116 if ((res = driver->detach_client(client))) {
117 dev_err(&isa_adapter.dev, "Failed, driver "
118 "%s not unregistered!\n",
119 driver->driver.name);
120 return res;
124 /* Get the driver off the core list */
125 driver_unregister(&driver->driver);
126 dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->driver.name);
128 return 0;
132 static int __init i2c_isa_init(void)
134 int err;
136 mutex_init(&isa_adapter.clist_lock);
137 INIT_LIST_HEAD(&isa_adapter.clients);
139 isa_adapter.nr = ANY_I2C_ISA_BUS;
140 isa_adapter.dev.parent = &platform_bus;
141 sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
142 isa_adapter.dev.driver = &i2c_adapter_driver;
143 isa_adapter.dev.release = &i2c_adapter_dev_release;
144 err = device_register(&isa_adapter.dev);
145 if (err) {
146 printk(KERN_ERR "i2c-isa: Failed to register device\n");
147 goto exit;
149 err = device_create_file(&isa_adapter.dev, &dev_attr_name);
150 if (err) {
151 printk(KERN_ERR "i2c-isa: Failed to create name file\n");
152 goto exit_unregister;
155 /* Add this adapter to the i2c_adapter class */
156 memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
157 isa_adapter.class_dev.dev = &isa_adapter.dev;
158 isa_adapter.class_dev.class = &i2c_adapter_class;
159 strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
160 BUS_ID_SIZE);
161 err = class_device_register(&isa_adapter.class_dev);
162 if (err) {
163 printk(KERN_ERR "i2c-isa: Failed to register class device\n");
164 goto exit_remove_name;
167 dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
169 return 0;
171 exit_remove_name:
172 device_remove_file(&isa_adapter.dev, &dev_attr_name);
173 exit_unregister:
174 init_completion(&isa_adapter.dev_released); /* Needed? */
175 device_unregister(&isa_adapter.dev);
176 wait_for_completion(&isa_adapter.dev_released);
177 exit:
178 return err;
181 static void __exit i2c_isa_exit(void)
183 #ifdef DEBUG
184 struct list_head *item, *_n;
185 struct i2c_client *client = NULL;
186 #endif
188 /* There should be no more active client */
189 #ifdef DEBUG
190 dev_dbg(&isa_adapter.dev, "Looking for clients\n");
191 list_for_each_safe(item, _n, &isa_adapter.clients) {
192 client = list_entry(item, struct i2c_client, list);
193 dev_err(&isa_adapter.dev, "Driver %s still has an active "
194 "ISA client at 0x%x\n", client->driver->driver.name,
195 client->addr);
197 if (client != NULL)
198 return;
199 #endif
201 /* Clean up the sysfs representation */
202 dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
203 init_completion(&isa_adapter.dev_released);
204 init_completion(&isa_adapter.class_dev_released);
205 class_device_unregister(&isa_adapter.class_dev);
206 device_remove_file(&isa_adapter.dev, &dev_attr_name);
207 device_unregister(&isa_adapter.dev);
209 /* Wait for sysfs to drop all references */
210 dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
211 wait_for_completion(&isa_adapter.dev_released);
212 wait_for_completion(&isa_adapter.class_dev_released);
214 dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
217 EXPORT_SYMBOL(i2c_isa_add_driver);
218 EXPORT_SYMBOL(i2c_isa_del_driver);
220 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
221 MODULE_DESCRIPTION("ISA bus access through i2c");
222 MODULE_LICENSE("GPL");
224 module_init(i2c_isa_init);
225 module_exit(i2c_isa_exit);