i2c: Class attribute cleanup
[powerpc.git] / drivers / i2c / busses / i2c-isa.c
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>
4
5     Based on the i2c-isa pseudo-adapter from the lm_sensors project
6     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
7
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.
12
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.
17
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.
21 */
22
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. */
34
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>
43
44 static u32 isa_func(struct i2c_adapter *adapter);
45
46 /* This is the actual algorithm we define */
47 static const struct i2c_algorithm isa_algorithm = {
48         .functionality  = isa_func,
49 };
50
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",
58 };
59
60 /* We can't do a thing... */
61 static u32 isa_func(struct i2c_adapter *adapter)
62 {
63         return 0;
64 }
65
66
67 /* We implement an interface which resembles i2c_{add,del}_driver,
68    but for i2c-isa drivers. We don't have to remember and handle lists
69    of drivers and adapters so this is much more simple, of course. */
70
71 int i2c_isa_add_driver(struct i2c_driver *driver)
72 {
73         int res;
74
75         /* Add the driver to the list of i2c drivers in the driver core */
76         driver->driver.bus = &i2c_bus_type;
77         res = driver_register(&driver->driver);
78         if (res)
79                 return res;
80         dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
81
82         /* Now look for clients */
83         res = driver->attach_adapter(&isa_adapter);
84         if (res) {
85                 dev_dbg(&isa_adapter.dev,
86                         "Driver %s failed to attach adapter, unregistering\n",
87                         driver->driver.name);
88                 driver_unregister(&driver->driver);
89         }
90         return res;
91 }
92
93 int i2c_isa_del_driver(struct i2c_driver *driver)
94 {
95         struct list_head *item, *_n;
96         struct i2c_client *client;
97         int res;
98
99         /* Detach all clients belonging to this one driver */
100         list_for_each_safe(item, _n, &isa_adapter.clients) {
101                 client = list_entry(item, struct i2c_client, list);
102                 if (client->driver != driver)
103                         continue;
104                 dev_dbg(&isa_adapter.dev, "Detaching client %s at 0x%x\n",
105                         client->name, client->addr);
106                 if ((res = driver->detach_client(client))) {
107                         dev_err(&isa_adapter.dev, "Failed, driver "
108                                 "%s not unregistered!\n",
109                                 driver->driver.name);
110                         return res;
111                 }
112         }
113
114         /* Get the driver off the core list */
115         driver_unregister(&driver->driver);
116         dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->driver.name);
117
118         return 0;
119 }
120
121
122 static int __init i2c_isa_init(void)
123 {
124         int err;
125
126         mutex_init(&isa_adapter.clist_lock);
127         INIT_LIST_HEAD(&isa_adapter.clients);
128
129         isa_adapter.nr = ANY_I2C_ISA_BUS;
130         isa_adapter.dev.parent = &platform_bus;
131         sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
132         isa_adapter.dev.release = &i2c_adapter_dev_release;
133         isa_adapter.dev.class = &i2c_adapter_class;
134         err = device_register(&isa_adapter.dev);
135         if (err) {
136                 printk(KERN_ERR "i2c-isa: Failed to register device\n");
137                 goto exit;
138         }
139
140         dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
141
142         return 0;
143
144 exit:
145         return err;
146 }
147
148 static void __exit i2c_isa_exit(void)
149 {
150 #ifdef DEBUG
151         struct list_head  *item, *_n;
152         struct i2c_client *client = NULL;
153 #endif
154
155         /* There should be no more active client */
156 #ifdef DEBUG
157         dev_dbg(&isa_adapter.dev, "Looking for clients\n");
158         list_for_each_safe(item, _n, &isa_adapter.clients) {
159                 client = list_entry(item, struct i2c_client, list);
160                 dev_err(&isa_adapter.dev, "Driver %s still has an active "
161                         "ISA client at 0x%x\n", client->driver->driver.name,
162                         client->addr);
163         }
164         if (client != NULL)
165                 return;
166 #endif
167
168         /* Clean up the sysfs representation */
169         dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
170         init_completion(&isa_adapter.dev_released);
171         device_unregister(&isa_adapter.dev);
172
173         /* Wait for sysfs to drop all references */
174         dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
175         wait_for_completion(&isa_adapter.dev_released);
176
177         dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
178 }
179
180 EXPORT_SYMBOL(i2c_isa_add_driver);
181 EXPORT_SYMBOL(i2c_isa_del_driver);
182
183 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
184 MODULE_DESCRIPTION("ISA bus access through i2c");
185 MODULE_LICENSE("GPL");
186
187 module_init(i2c_isa_init);
188 module_exit(i2c_isa_exit);