diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2006-01-19 11:39:33 -0500 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2006-01-19 11:39:33 -0500 |
commit | 944d79559d154c12becde0dab327016cf438f46c (patch) | |
tree | 50c101806f4d3b6585222dda060559eb4f3e005a /drivers/i2c | |
parent | d087e4bdd24ebe3ae3d0b265b6573ec901af4b4b (diff) | |
parent | 0f36b018b2e314d45af86449f1a97facb1fbe300 (diff) |
Merge branch 'master' of /usr/src/ntfs-2.6/
Diffstat (limited to 'drivers/i2c')
28 files changed, 489 insertions, 1390 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 4010fe92e72b..08d5b8fed2dc 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -236,27 +236,17 @@ config I2C_IXP2000 | |||
236 | This support is also available as a module. If so, the module | 236 | This support is also available as a module. If so, the module |
237 | will be called i2c-ixp2000. | 237 | will be called i2c-ixp2000. |
238 | 238 | ||
239 | config I2C_KEYWEST | 239 | config I2C_POWERMAC |
240 | tristate "Powermac Keywest I2C interface" | 240 | tristate "Powermac I2C interface" |
241 | depends on I2C && PPC_PMAC | 241 | depends on I2C && PPC_PMAC |
242 | default y | ||
242 | help | 243 | help |
243 | This supports the use of the I2C interface in the combo-I/O | 244 | This exposes the various PowerMac i2c interfaces to the linux i2c |
244 | chip on recent Apple machines. Say Y if you have such a machine. | 245 | layer and to userland. It is used by various drivers on the powemac |
245 | 246 | platform, thus should generally be enabled. | |
246 | This support is also available as a module. If so, the module | ||
247 | will be called i2c-keywest. | ||
248 | |||
249 | config I2C_PMAC_SMU | ||
250 | tristate "Powermac SMU I2C interface" | ||
251 | depends on I2C && PMAC_SMU | ||
252 | help | ||
253 | This supports the use of the I2C interface in the SMU | ||
254 | chip on recent Apple machines like the iMac G5. It is used | ||
255 | among others by the thermal control driver for those machines. | ||
256 | Say Y if you have such a machine. | ||
257 | 247 | ||
258 | This support is also available as a module. If so, the module | 248 | This support is also available as a module. If so, the module |
259 | will be called i2c-pmac-smu. | 249 | will be called i2c-powermac. |
260 | 250 | ||
261 | config I2C_MPC | 251 | config I2C_MPC |
262 | tristate "MPC107/824x/85xx/52xx" | 252 | tristate "MPC107/824x/85xx/52xx" |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index f1df00f66c6c..b44831dff683 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -19,8 +19,7 @@ obj-$(CONFIG_I2C_ISA) += i2c-isa.o | |||
19 | obj-$(CONFIG_I2C_ITE) += i2c-ite.o | 19 | obj-$(CONFIG_I2C_ITE) += i2c-ite.o |
20 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o | 20 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o |
21 | obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o | 21 | obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o |
22 | obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o | 22 | obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o |
23 | obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o | ||
24 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o | 23 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o |
25 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o | 24 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o |
26 | obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o | 25 | obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ac3eafa8aac0..1c752ddc10e2 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -468,8 +468,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, | |||
468 | return -1; | 468 | return -1; |
469 | } | 469 | } |
470 | 470 | ||
471 | if (hwpec) | 471 | outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */ |
472 | outb_p(1, SMBAUXCTL); /* enable hardware PEC */ | ||
473 | 472 | ||
474 | if(block) | 473 | if(block) |
475 | ret = i801_block_transaction(data, read_write, size, hwpec); | 474 | ret = i801_block_transaction(data, read_write, size, hwpec); |
@@ -478,9 +477,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, | |||
478 | ret = i801_transaction(); | 477 | ret = i801_transaction(); |
479 | } | 478 | } |
480 | 479 | ||
481 | if (hwpec) | ||
482 | outb_p(0, SMBAUXCTL); /* disable hardware PEC */ | ||
483 | |||
484 | if(block) | 480 | if(block) |
485 | return ret; | 481 | return ret; |
486 | if(ret) | 482 | if(ret) |
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 1a587253d716..87fae937e666 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c | |||
@@ -725,6 +725,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ | |||
725 | strcpy(adap->name, "IBM IIC"); | 725 | strcpy(adap->name, "IBM IIC"); |
726 | i2c_set_adapdata(adap, dev); | 726 | i2c_set_adapdata(adap, dev); |
727 | adap->id = I2C_HW_OCP; | 727 | adap->id = I2C_HW_OCP; |
728 | adap->class = I2C_CLASS_HWMON; | ||
728 | adap->algo = &iic_algo; | 729 | adap->algo = &iic_algo; |
729 | adap->client_register = NULL; | 730 | adap->client_register = NULL; |
730 | adap->client_unregister = NULL; | 731 | adap->client_unregister = NULL; |
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 03672c9ca409..9f2ffef4d812 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c | |||
@@ -92,15 +92,13 @@ int i2c_isa_add_driver(struct i2c_driver *driver) | |||
92 | int res; | 92 | int res; |
93 | 93 | ||
94 | /* Add the driver to the list of i2c drivers in the driver core */ | 94 | /* Add the driver to the list of i2c drivers in the driver core */ |
95 | driver->driver.name = driver->name; | ||
96 | driver->driver.owner = driver->owner; | ||
97 | driver->driver.bus = &i2c_bus_type; | 95 | driver->driver.bus = &i2c_bus_type; |
98 | driver->driver.probe = i2c_isa_device_probe; | 96 | driver->driver.probe = i2c_isa_device_probe; |
99 | driver->driver.remove = i2c_isa_device_remove; | 97 | driver->driver.remove = i2c_isa_device_remove; |
100 | res = driver_register(&driver->driver); | 98 | res = driver_register(&driver->driver); |
101 | if (res) | 99 | if (res) |
102 | return res; | 100 | return res; |
103 | dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name); | 101 | dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name); |
104 | 102 | ||
105 | /* Now look for clients */ | 103 | /* Now look for clients */ |
106 | driver->attach_adapter(&isa_adapter); | 104 | driver->attach_adapter(&isa_adapter); |
@@ -124,14 +122,14 @@ int i2c_isa_del_driver(struct i2c_driver *driver) | |||
124 | if ((res = driver->detach_client(client))) { | 122 | if ((res = driver->detach_client(client))) { |
125 | dev_err(&isa_adapter.dev, "Failed, driver " | 123 | dev_err(&isa_adapter.dev, "Failed, driver " |
126 | "%s not unregistered!\n", | 124 | "%s not unregistered!\n", |
127 | driver->name); | 125 | driver->driver.name); |
128 | return res; | 126 | return res; |
129 | } | 127 | } |
130 | } | 128 | } |
131 | 129 | ||
132 | /* Get the driver off the core list */ | 130 | /* Get the driver off the core list */ |
133 | driver_unregister(&driver->driver); | 131 | driver_unregister(&driver->driver); |
134 | dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name); | 132 | dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->driver.name); |
135 | 133 | ||
136 | return 0; | 134 | return 0; |
137 | } | 135 | } |
@@ -176,7 +174,7 @@ static void __exit i2c_isa_exit(void) | |||
176 | list_for_each_safe(item, _n, &isa_adapter.clients) { | 174 | list_for_each_safe(item, _n, &isa_adapter.clients) { |
177 | client = list_entry(item, struct i2c_client, list); | 175 | client = list_entry(item, struct i2c_client, list); |
178 | dev_err(&isa_adapter.dev, "Driver %s still has an active " | 176 | dev_err(&isa_adapter.dev, "Driver %s still has an active " |
179 | "ISA client at 0x%x\n", client->driver->name, | 177 | "ISA client at 0x%x\n", client->driver->driver.name, |
180 | client->addr); | 178 | client->addr); |
181 | } | 179 | } |
182 | if (client != NULL) | 180 | if (client != NULL) |
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c deleted file mode 100644 index d61f748278fc..000000000000 --- a/drivers/i2c/busses/i2c-keywest.c +++ /dev/null | |||
@@ -1,751 +0,0 @@ | |||
1 | /* | ||
2 | i2c Support for Apple Keywest I2C Bus Controller | ||
3 | |||
4 | Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | |||
6 | Original work by | ||
7 | |||
8 | Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | |||
24 | Changes: | ||
25 | |||
26 | 2001/12/13 BenH New implementation | ||
27 | 2001/12/15 BenH Add support for "byte" and "quick" | ||
28 | transfers. Add i2c_xfer routine. | ||
29 | 2003/09/21 BenH Rework state machine with Paulus help | ||
30 | 2004/01/21 BenH Merge in Greg KH changes, polled mode is back | ||
31 | 2004/02/05 BenH Merge 64 bits fixes from the g5 ppc64 tree | ||
32 | |||
33 | My understanding of the various modes supported by keywest are: | ||
34 | |||
35 | - Dumb mode : not implemented, probably direct tweaking of lines | ||
36 | - Standard mode : simple i2c transaction of type | ||
37 | S Addr R/W A Data A Data ... T | ||
38 | - Standard sub mode : combined 8 bit subaddr write with data read | ||
39 | S Addr R/W A SubAddr A Data A Data ... T | ||
40 | - Combined mode : Subaddress and Data sequences appended with no stop | ||
41 | S Addr R/W A SubAddr S Addr R/W A Data A Data ... T | ||
42 | |||
43 | Currently, this driver uses only Standard mode for i2c xfer, and | ||
44 | smbus byte & quick transfers ; and uses StandardSub mode for | ||
45 | other smbus transfers instead of combined as we need that for the | ||
46 | sound driver to be happy | ||
47 | */ | ||
48 | |||
49 | #include <linux/module.h> | ||
50 | #include <linux/kernel.h> | ||
51 | #include <linux/ioport.h> | ||
52 | #include <linux/pci.h> | ||
53 | #include <linux/types.h> | ||
54 | #include <linux/delay.h> | ||
55 | #include <linux/i2c.h> | ||
56 | #include <linux/init.h> | ||
57 | #include <linux/mm.h> | ||
58 | #include <linux/timer.h> | ||
59 | #include <linux/spinlock.h> | ||
60 | #include <linux/completion.h> | ||
61 | #include <linux/interrupt.h> | ||
62 | |||
63 | #include <asm/io.h> | ||
64 | #include <asm/prom.h> | ||
65 | #include <asm/machdep.h> | ||
66 | #include <asm/pmac_feature.h> | ||
67 | #include <asm/pmac_low_i2c.h> | ||
68 | |||
69 | #include "i2c-keywest.h" | ||
70 | |||
71 | #undef POLLED_MODE | ||
72 | |||
73 | /* Some debug macros */ | ||
74 | #define WRONG_STATE(name) do {\ | ||
75 | pr_debug("KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ | ||
76 | name, __kw_state_names[iface->state], isr); \ | ||
77 | } while(0) | ||
78 | |||
79 | #ifdef DEBUG | ||
80 | static const char *__kw_state_names[] = { | ||
81 | "state_idle", | ||
82 | "state_addr", | ||
83 | "state_read", | ||
84 | "state_write", | ||
85 | "state_stop", | ||
86 | "state_dead" | ||
87 | }; | ||
88 | #endif /* DEBUG */ | ||
89 | |||
90 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
91 | MODULE_DESCRIPTION("I2C driver for Apple's Keywest"); | ||
92 | MODULE_LICENSE("GPL"); | ||
93 | |||
94 | #ifdef POLLED_MODE | ||
95 | /* Don't schedule, the g5 fan controller is too | ||
96 | * timing sensitive | ||
97 | */ | ||
98 | static u8 | ||
99 | wait_interrupt(struct keywest_iface* iface) | ||
100 | { | ||
101 | int i; | ||
102 | u8 isr; | ||
103 | |||
104 | for (i = 0; i < 200000; i++) { | ||
105 | isr = read_reg(reg_isr) & KW_I2C_IRQ_MASK; | ||
106 | if (isr != 0) | ||
107 | return isr; | ||
108 | udelay(10); | ||
109 | } | ||
110 | return isr; | ||
111 | } | ||
112 | #endif /* POLLED_MODE */ | ||
113 | |||
114 | static void | ||
115 | do_stop(struct keywest_iface* iface, int result) | ||
116 | { | ||
117 | write_reg(reg_control, KW_I2C_CTL_STOP); | ||
118 | iface->state = state_stop; | ||
119 | iface->result = result; | ||
120 | } | ||
121 | |||
122 | /* Main state machine for standard & standard sub mode */ | ||
123 | static void | ||
124 | handle_interrupt(struct keywest_iface *iface, u8 isr) | ||
125 | { | ||
126 | int ack; | ||
127 | |||
128 | if (isr == 0) { | ||
129 | if (iface->state != state_stop) { | ||
130 | pr_debug("KW: Timeout !\n"); | ||
131 | do_stop(iface, -EIO); | ||
132 | } | ||
133 | if (iface->state == state_stop) { | ||
134 | ack = read_reg(reg_status); | ||
135 | if (!(ack & KW_I2C_STAT_BUSY)) { | ||
136 | iface->state = state_idle; | ||
137 | write_reg(reg_ier, 0x00); | ||
138 | #ifndef POLLED_MODE | ||
139 | complete(&iface->complete); | ||
140 | #endif /* POLLED_MODE */ | ||
141 | } | ||
142 | } | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | if (isr & KW_I2C_IRQ_ADDR) { | ||
147 | ack = read_reg(reg_status); | ||
148 | if (iface->state != state_addr) { | ||
149 | write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
150 | WRONG_STATE("KW_I2C_IRQ_ADDR"); | ||
151 | do_stop(iface, -EIO); | ||
152 | return; | ||
153 | } | ||
154 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
155 | iface->state = state_stop; | ||
156 | iface->result = -ENODEV; | ||
157 | pr_debug("KW: NAK on address\n"); | ||
158 | } else { | ||
159 | /* Handle rw "quick" mode */ | ||
160 | if (iface->datalen == 0) { | ||
161 | do_stop(iface, 0); | ||
162 | } else if (iface->read_write == I2C_SMBUS_READ) { | ||
163 | iface->state = state_read; | ||
164 | if (iface->datalen > 1) | ||
165 | write_reg(reg_control, KW_I2C_CTL_AAK); | ||
166 | } else { | ||
167 | iface->state = state_write; | ||
168 | write_reg(reg_data, *(iface->data++)); | ||
169 | iface->datalen--; | ||
170 | } | ||
171 | } | ||
172 | write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
173 | } | ||
174 | |||
175 | if (isr & KW_I2C_IRQ_DATA) { | ||
176 | if (iface->state == state_read) { | ||
177 | *(iface->data++) = read_reg(reg_data); | ||
178 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
179 | iface->datalen--; | ||
180 | if (iface->datalen == 0) | ||
181 | iface->state = state_stop; | ||
182 | else if (iface->datalen == 1) | ||
183 | write_reg(reg_control, 0); | ||
184 | } else if (iface->state == state_write) { | ||
185 | /* Check ack status */ | ||
186 | ack = read_reg(reg_status); | ||
187 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
188 | pr_debug("KW: nack on data write (%x): %x\n", | ||
189 | iface->data[-1], ack); | ||
190 | do_stop(iface, -EIO); | ||
191 | } else if (iface->datalen) { | ||
192 | write_reg(reg_data, *(iface->data++)); | ||
193 | iface->datalen--; | ||
194 | } else { | ||
195 | write_reg(reg_control, KW_I2C_CTL_STOP); | ||
196 | iface->state = state_stop; | ||
197 | iface->result = 0; | ||
198 | } | ||
199 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
200 | } else { | ||
201 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
202 | WRONG_STATE("KW_I2C_IRQ_DATA"); | ||
203 | if (iface->state != state_stop) | ||
204 | do_stop(iface, -EIO); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | if (isr & KW_I2C_IRQ_STOP) { | ||
209 | write_reg(reg_isr, KW_I2C_IRQ_STOP); | ||
210 | if (iface->state != state_stop) { | ||
211 | WRONG_STATE("KW_I2C_IRQ_STOP"); | ||
212 | iface->result = -EIO; | ||
213 | } | ||
214 | iface->state = state_idle; | ||
215 | write_reg(reg_ier, 0x00); | ||
216 | #ifndef POLLED_MODE | ||
217 | complete(&iface->complete); | ||
218 | #endif /* POLLED_MODE */ | ||
219 | } | ||
220 | |||
221 | if (isr & KW_I2C_IRQ_START) | ||
222 | write_reg(reg_isr, KW_I2C_IRQ_START); | ||
223 | } | ||
224 | |||
225 | #ifndef POLLED_MODE | ||
226 | |||
227 | /* Interrupt handler */ | ||
228 | static irqreturn_t | ||
229 | keywest_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
230 | { | ||
231 | struct keywest_iface *iface = (struct keywest_iface *)dev_id; | ||
232 | unsigned long flags; | ||
233 | |||
234 | spin_lock_irqsave(&iface->lock, flags); | ||
235 | del_timer(&iface->timeout_timer); | ||
236 | handle_interrupt(iface, read_reg(reg_isr)); | ||
237 | if (iface->state != state_idle) { | ||
238 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
239 | add_timer(&iface->timeout_timer); | ||
240 | } | ||
241 | spin_unlock_irqrestore(&iface->lock, flags); | ||
242 | return IRQ_HANDLED; | ||
243 | } | ||
244 | |||
245 | static void | ||
246 | keywest_timeout(unsigned long data) | ||
247 | { | ||
248 | struct keywest_iface *iface = (struct keywest_iface *)data; | ||
249 | unsigned long flags; | ||
250 | |||
251 | pr_debug("timeout !\n"); | ||
252 | spin_lock_irqsave(&iface->lock, flags); | ||
253 | handle_interrupt(iface, read_reg(reg_isr)); | ||
254 | if (iface->state != state_idle) { | ||
255 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
256 | add_timer(&iface->timeout_timer); | ||
257 | } | ||
258 | spin_unlock_irqrestore(&iface->lock, flags); | ||
259 | } | ||
260 | |||
261 | #endif /* POLLED_MODE */ | ||
262 | |||
263 | /* | ||
264 | * SMBUS-type transfer entrypoint | ||
265 | */ | ||
266 | static s32 | ||
267 | keywest_smbus_xfer( struct i2c_adapter* adap, | ||
268 | u16 addr, | ||
269 | unsigned short flags, | ||
270 | char read_write, | ||
271 | u8 command, | ||
272 | int size, | ||
273 | union i2c_smbus_data* data) | ||
274 | { | ||
275 | struct keywest_chan* chan = i2c_get_adapdata(adap); | ||
276 | struct keywest_iface* iface = chan->iface; | ||
277 | int len; | ||
278 | u8* buffer; | ||
279 | u16 cur_word; | ||
280 | int rc = 0; | ||
281 | |||
282 | if (iface->state == state_dead) | ||
283 | return -ENXIO; | ||
284 | |||
285 | /* Prepare datas & select mode */ | ||
286 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
287 | switch (size) { | ||
288 | case I2C_SMBUS_QUICK: | ||
289 | len = 0; | ||
290 | buffer = NULL; | ||
291 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
292 | break; | ||
293 | case I2C_SMBUS_BYTE: | ||
294 | len = 1; | ||
295 | buffer = &data->byte; | ||
296 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
297 | break; | ||
298 | case I2C_SMBUS_BYTE_DATA: | ||
299 | len = 1; | ||
300 | buffer = &data->byte; | ||
301 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
302 | break; | ||
303 | case I2C_SMBUS_WORD_DATA: | ||
304 | len = 2; | ||
305 | cur_word = cpu_to_le16(data->word); | ||
306 | buffer = (u8 *)&cur_word; | ||
307 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
308 | break; | ||
309 | case I2C_SMBUS_BLOCK_DATA: | ||
310 | len = data->block[0]; | ||
311 | buffer = &data->block[1]; | ||
312 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
313 | break; | ||
314 | default: | ||
315 | return -1; | ||
316 | } | ||
317 | |||
318 | /* Turn a standardsub read into a combined mode access */ | ||
319 | if (read_write == I2C_SMBUS_READ | ||
320 | && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) { | ||
321 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
322 | iface->cur_mode |= KW_I2C_MODE_COMBINED; | ||
323 | } | ||
324 | |||
325 | /* Original driver had this limitation */ | ||
326 | if (len > 32) | ||
327 | len = 32; | ||
328 | |||
329 | if (pmac_low_i2c_lock(iface->node)) | ||
330 | return -ENXIO; | ||
331 | |||
332 | pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n", | ||
333 | chan->chan_no, addr, len, read_write == I2C_SMBUS_READ); | ||
334 | |||
335 | iface->data = buffer; | ||
336 | iface->datalen = len; | ||
337 | iface->state = state_addr; | ||
338 | iface->result = 0; | ||
339 | iface->read_write = read_write; | ||
340 | |||
341 | /* Setup channel & clear pending irqs */ | ||
342 | write_reg(reg_isr, read_reg(reg_isr)); | ||
343 | write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); | ||
344 | write_reg(reg_status, 0); | ||
345 | |||
346 | /* Set up address and r/w bit */ | ||
347 | write_reg(reg_addr, | ||
348 | (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); | ||
349 | |||
350 | /* Set up the sub address */ | ||
351 | if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB | ||
352 | || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED) | ||
353 | write_reg(reg_subaddr, command); | ||
354 | |||
355 | #ifndef POLLED_MODE | ||
356 | /* Arm timeout */ | ||
357 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
358 | add_timer(&iface->timeout_timer); | ||
359 | #endif | ||
360 | |||
361 | /* Start sending address & enable interrupt*/ | ||
362 | write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
363 | write_reg(reg_ier, KW_I2C_IRQ_MASK); | ||
364 | |||
365 | #ifdef POLLED_MODE | ||
366 | pr_debug("using polled mode...\n"); | ||
367 | /* State machine, to turn into an interrupt handler */ | ||
368 | while(iface->state != state_idle) { | ||
369 | unsigned long flags; | ||
370 | |||
371 | u8 isr = wait_interrupt(iface); | ||
372 | spin_lock_irqsave(&iface->lock, flags); | ||
373 | handle_interrupt(iface, isr); | ||
374 | spin_unlock_irqrestore(&iface->lock, flags); | ||
375 | } | ||
376 | #else /* POLLED_MODE */ | ||
377 | pr_debug("using interrupt mode...\n"); | ||
378 | wait_for_completion(&iface->complete); | ||
379 | #endif /* POLLED_MODE */ | ||
380 | |||
381 | rc = iface->result; | ||
382 | pr_debug("transfer done, result: %d\n", rc); | ||
383 | |||
384 | if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ) | ||
385 | data->word = le16_to_cpu(cur_word); | ||
386 | |||
387 | /* Release sem */ | ||
388 | pmac_low_i2c_unlock(iface->node); | ||
389 | |||
390 | return rc; | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Generic i2c master transfer entrypoint | ||
395 | */ | ||
396 | static int | ||
397 | keywest_xfer( struct i2c_adapter *adap, | ||
398 | struct i2c_msg *msgs, | ||
399 | int num) | ||
400 | { | ||
401 | struct keywest_chan* chan = i2c_get_adapdata(adap); | ||
402 | struct keywest_iface* iface = chan->iface; | ||
403 | struct i2c_msg *pmsg; | ||
404 | int i, completed; | ||
405 | int rc = 0; | ||
406 | |||
407 | if (iface->state == state_dead) | ||
408 | return -ENXIO; | ||
409 | |||
410 | if (pmac_low_i2c_lock(iface->node)) | ||
411 | return -ENXIO; | ||
412 | |||
413 | /* Set adapter to standard mode */ | ||
414 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
415 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
416 | |||
417 | completed = 0; | ||
418 | for (i = 0; rc >= 0 && i < num;) { | ||
419 | u8 addr; | ||
420 | |||
421 | pmsg = &msgs[i++]; | ||
422 | addr = pmsg->addr; | ||
423 | if (pmsg->flags & I2C_M_TEN) { | ||
424 | printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n"); | ||
425 | rc = -EINVAL; | ||
426 | break; | ||
427 | } | ||
428 | pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n", | ||
429 | chan->chan_no, | ||
430 | pmsg->flags & I2C_M_RD ? "read" : "write", | ||
431 | pmsg->len, addr, i, num); | ||
432 | |||
433 | /* Setup channel & clear pending irqs */ | ||
434 | write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); | ||
435 | write_reg(reg_isr, read_reg(reg_isr)); | ||
436 | write_reg(reg_status, 0); | ||
437 | |||
438 | iface->data = pmsg->buf; | ||
439 | iface->datalen = pmsg->len; | ||
440 | iface->state = state_addr; | ||
441 | iface->result = 0; | ||
442 | if (pmsg->flags & I2C_M_RD) | ||
443 | iface->read_write = I2C_SMBUS_READ; | ||
444 | else | ||
445 | iface->read_write = I2C_SMBUS_WRITE; | ||
446 | |||
447 | /* Set up address and r/w bit */ | ||
448 | if (pmsg->flags & I2C_M_REV_DIR_ADDR) | ||
449 | addr ^= 1; | ||
450 | write_reg(reg_addr, | ||
451 | (addr << 1) | | ||
452 | ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); | ||
453 | |||
454 | #ifndef POLLED_MODE | ||
455 | /* Arm timeout */ | ||
456 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
457 | add_timer(&iface->timeout_timer); | ||
458 | #endif | ||
459 | |||
460 | /* Start sending address & enable interrupt*/ | ||
461 | write_reg(reg_ier, KW_I2C_IRQ_MASK); | ||
462 | write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
463 | |||
464 | #ifdef POLLED_MODE | ||
465 | pr_debug("using polled mode...\n"); | ||
466 | /* State machine, to turn into an interrupt handler */ | ||
467 | while(iface->state != state_idle) { | ||
468 | u8 isr = wait_interrupt(iface); | ||
469 | handle_interrupt(iface, isr); | ||
470 | } | ||
471 | #else /* POLLED_MODE */ | ||
472 | pr_debug("using interrupt mode...\n"); | ||
473 | wait_for_completion(&iface->complete); | ||
474 | #endif /* POLLED_MODE */ | ||
475 | |||
476 | rc = iface->result; | ||
477 | if (rc == 0) | ||
478 | completed++; | ||
479 | pr_debug("transfer done, result: %d\n", rc); | ||
480 | } | ||
481 | |||
482 | /* Release sem */ | ||
483 | pmac_low_i2c_unlock(iface->node); | ||
484 | |||
485 | return completed; | ||
486 | } | ||
487 | |||
488 | static u32 | ||
489 | keywest_func(struct i2c_adapter * adapter) | ||
490 | { | ||
491 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
492 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
493 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
494 | } | ||
495 | |||
496 | /* For now, we only handle combined mode (smbus) */ | ||
497 | static struct i2c_algorithm keywest_algorithm = { | ||
498 | .smbus_xfer = keywest_smbus_xfer, | ||
499 | .master_xfer = keywest_xfer, | ||
500 | .functionality = keywest_func, | ||
501 | }; | ||
502 | |||
503 | |||
504 | static int | ||
505 | create_iface(struct device_node *np, struct device *dev) | ||
506 | { | ||
507 | unsigned long steps; | ||
508 | unsigned bsteps, tsize, i, nchan, addroffset; | ||
509 | struct keywest_iface* iface; | ||
510 | u32 *psteps, *prate; | ||
511 | int rc; | ||
512 | |||
513 | if (np->n_intrs < 1 || np->n_addrs < 1) { | ||
514 | printk(KERN_ERR "%s: Missing interrupt or address !\n", | ||
515 | np->full_name); | ||
516 | return -ENODEV; | ||
517 | } | ||
518 | if (pmac_low_i2c_lock(np)) | ||
519 | return -ENODEV; | ||
520 | |||
521 | psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); | ||
522 | steps = psteps ? (*psteps) : 0x10; | ||
523 | |||
524 | /* Hrm... maybe we can be smarter here */ | ||
525 | for (bsteps = 0; (steps & 0x01) == 0; bsteps++) | ||
526 | steps >>= 1; | ||
527 | |||
528 | if (np->parent->name[0] == 'u') { | ||
529 | nchan = 2; | ||
530 | addroffset = 3; | ||
531 | } else { | ||
532 | addroffset = 0; | ||
533 | nchan = 1; | ||
534 | } | ||
535 | |||
536 | tsize = sizeof(struct keywest_iface) + | ||
537 | (sizeof(struct keywest_chan) + 4) * nchan; | ||
538 | iface = kzalloc(tsize, GFP_KERNEL); | ||
539 | if (iface == NULL) { | ||
540 | printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n"); | ||
541 | pmac_low_i2c_unlock(np); | ||
542 | return -ENOMEM; | ||
543 | } | ||
544 | spin_lock_init(&iface->lock); | ||
545 | init_completion(&iface->complete); | ||
546 | iface->node = of_node_get(np); | ||
547 | iface->bsteps = bsteps; | ||
548 | iface->chan_count = nchan; | ||
549 | iface->state = state_idle; | ||
550 | iface->irq = np->intrs[0].line; | ||
551 | iface->channels = (struct keywest_chan *) | ||
552 | (((unsigned long)(iface + 1) + 3UL) & ~3UL); | ||
553 | iface->base = ioremap(np->addrs[0].address + addroffset, | ||
554 | np->addrs[0].size); | ||
555 | if (!iface->base) { | ||
556 | printk(KERN_ERR "i2c-keywest: can't map inteface !\n"); | ||
557 | kfree(iface); | ||
558 | pmac_low_i2c_unlock(np); | ||
559 | return -ENOMEM; | ||
560 | } | ||
561 | |||
562 | #ifndef POLLED_MODE | ||
563 | init_timer(&iface->timeout_timer); | ||
564 | iface->timeout_timer.function = keywest_timeout; | ||
565 | iface->timeout_timer.data = (unsigned long)iface; | ||
566 | #endif | ||
567 | |||
568 | /* Select interface rate */ | ||
569 | iface->cur_mode = KW_I2C_MODE_100KHZ; | ||
570 | prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); | ||
571 | if (prate) switch(*prate) { | ||
572 | case 100: | ||
573 | iface->cur_mode = KW_I2C_MODE_100KHZ; | ||
574 | break; | ||
575 | case 50: | ||
576 | iface->cur_mode = KW_I2C_MODE_50KHZ; | ||
577 | break; | ||
578 | case 25: | ||
579 | iface->cur_mode = KW_I2C_MODE_25KHZ; | ||
580 | break; | ||
581 | default: | ||
582 | printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n", | ||
583 | (long)*prate); | ||
584 | } | ||
585 | |||
586 | /* Select standard mode by default */ | ||
587 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
588 | |||
589 | /* Write mode */ | ||
590 | write_reg(reg_mode, iface->cur_mode); | ||
591 | |||
592 | /* Switch interrupts off & clear them*/ | ||
593 | write_reg(reg_ier, 0x00); | ||
594 | write_reg(reg_isr, KW_I2C_IRQ_MASK); | ||
595 | |||
596 | #ifndef POLLED_MODE | ||
597 | /* Request chip interrupt */ | ||
598 | rc = request_irq(iface->irq, keywest_irq, SA_INTERRUPT, "keywest i2c", iface); | ||
599 | if (rc) { | ||
600 | printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); | ||
601 | iounmap(iface->base); | ||
602 | kfree(iface); | ||
603 | pmac_low_i2c_unlock(np); | ||
604 | return -ENODEV; | ||
605 | } | ||
606 | #endif /* POLLED_MODE */ | ||
607 | |||
608 | pmac_low_i2c_unlock(np); | ||
609 | dev_set_drvdata(dev, iface); | ||
610 | |||
611 | for (i=0; i<nchan; i++) { | ||
612 | struct keywest_chan* chan = &iface->channels[i]; | ||
613 | |||
614 | sprintf(chan->adapter.name, "%s %d", np->parent->name, i); | ||
615 | chan->iface = iface; | ||
616 | chan->chan_no = i; | ||
617 | chan->adapter.algo = &keywest_algorithm; | ||
618 | chan->adapter.algo_data = NULL; | ||
619 | chan->adapter.client_register = NULL; | ||
620 | chan->adapter.client_unregister = NULL; | ||
621 | i2c_set_adapdata(&chan->adapter, chan); | ||
622 | chan->adapter.dev.parent = dev; | ||
623 | |||
624 | rc = i2c_add_adapter(&chan->adapter); | ||
625 | if (rc) { | ||
626 | printk("i2c-keywest.c: Adapter %s registration failed\n", | ||
627 | chan->adapter.name); | ||
628 | i2c_set_adapdata(&chan->adapter, NULL); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n", | ||
633 | np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int | ||
639 | dispose_iface(struct device *dev) | ||
640 | { | ||
641 | struct keywest_iface *iface = dev_get_drvdata(dev); | ||
642 | int i, rc; | ||
643 | |||
644 | /* Make sure we stop all activity */ | ||
645 | if (pmac_low_i2c_lock(iface->node)) | ||
646 | return -ENODEV; | ||
647 | |||
648 | #ifndef POLLED_MODE | ||
649 | spin_lock_irq(&iface->lock); | ||
650 | while (iface->state != state_idle) { | ||
651 | spin_unlock_irq(&iface->lock); | ||
652 | msleep(100); | ||
653 | spin_lock_irq(&iface->lock); | ||
654 | } | ||
655 | #endif /* POLLED_MODE */ | ||
656 | iface->state = state_dead; | ||
657 | #ifndef POLLED_MODE | ||
658 | spin_unlock_irq(&iface->lock); | ||
659 | free_irq(iface->irq, iface); | ||
660 | #endif /* POLLED_MODE */ | ||
661 | |||
662 | pmac_low_i2c_unlock(iface->node); | ||
663 | |||
664 | /* Release all channels */ | ||
665 | for (i=0; i<iface->chan_count; i++) { | ||
666 | struct keywest_chan* chan = &iface->channels[i]; | ||
667 | if (i2c_get_adapdata(&chan->adapter) == NULL) | ||
668 | continue; | ||
669 | rc = i2c_del_adapter(&chan->adapter); | ||
670 | i2c_set_adapdata(&chan->adapter, NULL); | ||
671 | /* We aren't that prepared to deal with this... */ | ||
672 | if (rc) | ||
673 | printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); | ||
674 | } | ||
675 | iounmap(iface->base); | ||
676 | dev_set_drvdata(dev, NULL); | ||
677 | of_node_put(iface->node); | ||
678 | kfree(iface); | ||
679 | |||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static int | ||
684 | create_iface_macio(struct macio_dev* dev, const struct of_device_id *match) | ||
685 | { | ||
686 | return create_iface(dev->ofdev.node, &dev->ofdev.dev); | ||
687 | } | ||
688 | |||
689 | static int | ||
690 | dispose_iface_macio(struct macio_dev* dev) | ||
691 | { | ||
692 | return dispose_iface(&dev->ofdev.dev); | ||
693 | } | ||
694 | |||
695 | static int | ||
696 | create_iface_of_platform(struct of_device* dev, const struct of_device_id *match) | ||
697 | { | ||
698 | return create_iface(dev->node, &dev->dev); | ||
699 | } | ||
700 | |||
701 | static int | ||
702 | dispose_iface_of_platform(struct of_device* dev) | ||
703 | { | ||
704 | return dispose_iface(&dev->dev); | ||
705 | } | ||
706 | |||
707 | static struct of_device_id i2c_keywest_match[] = | ||
708 | { | ||
709 | { | ||
710 | .type = "i2c", | ||
711 | .compatible = "keywest" | ||
712 | }, | ||
713 | {}, | ||
714 | }; | ||
715 | |||
716 | static struct macio_driver i2c_keywest_macio_driver = | ||
717 | { | ||
718 | .owner = THIS_MODULE, | ||
719 | .name = "i2c-keywest", | ||
720 | .match_table = i2c_keywest_match, | ||
721 | .probe = create_iface_macio, | ||
722 | .remove = dispose_iface_macio | ||
723 | }; | ||
724 | |||
725 | static struct of_platform_driver i2c_keywest_of_platform_driver = | ||
726 | { | ||
727 | .owner = THIS_MODULE, | ||
728 | .name = "i2c-keywest", | ||
729 | .match_table = i2c_keywest_match, | ||
730 | .probe = create_iface_of_platform, | ||
731 | .remove = dispose_iface_of_platform | ||
732 | }; | ||
733 | |||
734 | static int __init | ||
735 | i2c_keywest_init(void) | ||
736 | { | ||
737 | of_register_driver(&i2c_keywest_of_platform_driver); | ||
738 | macio_register_driver(&i2c_keywest_macio_driver); | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | static void __exit | ||
744 | i2c_keywest_cleanup(void) | ||
745 | { | ||
746 | of_unregister_driver(&i2c_keywest_of_platform_driver); | ||
747 | macio_unregister_driver(&i2c_keywest_macio_driver); | ||
748 | } | ||
749 | |||
750 | module_init(i2c_keywest_init); | ||
751 | module_exit(i2c_keywest_cleanup); | ||
diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h deleted file mode 100644 index c5022e1ca6ff..000000000000 --- a/drivers/i2c/busses/i2c-keywest.h +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | #ifndef __I2C_KEYWEST_H__ | ||
2 | #define __I2C_KEYWEST_H__ | ||
3 | |||
4 | /* The Tumbler audio equalizer can be really slow sometimes */ | ||
5 | #define POLL_TIMEOUT (2*HZ) | ||
6 | |||
7 | /* Register indices */ | ||
8 | typedef enum { | ||
9 | reg_mode = 0, | ||
10 | reg_control, | ||
11 | reg_status, | ||
12 | reg_isr, | ||
13 | reg_ier, | ||
14 | reg_addr, | ||
15 | reg_subaddr, | ||
16 | reg_data | ||
17 | } reg_t; | ||
18 | |||
19 | |||
20 | /* Mode register */ | ||
21 | #define KW_I2C_MODE_100KHZ 0x00 | ||
22 | #define KW_I2C_MODE_50KHZ 0x01 | ||
23 | #define KW_I2C_MODE_25KHZ 0x02 | ||
24 | #define KW_I2C_MODE_DUMB 0x00 | ||
25 | #define KW_I2C_MODE_STANDARD 0x04 | ||
26 | #define KW_I2C_MODE_STANDARDSUB 0x08 | ||
27 | #define KW_I2C_MODE_COMBINED 0x0C | ||
28 | #define KW_I2C_MODE_MODE_MASK 0x0C | ||
29 | #define KW_I2C_MODE_CHAN_MASK 0xF0 | ||
30 | |||
31 | /* Control register */ | ||
32 | #define KW_I2C_CTL_AAK 0x01 | ||
33 | #define KW_I2C_CTL_XADDR 0x02 | ||
34 | #define KW_I2C_CTL_STOP 0x04 | ||
35 | #define KW_I2C_CTL_START 0x08 | ||
36 | |||
37 | /* Status register */ | ||
38 | #define KW_I2C_STAT_BUSY 0x01 | ||
39 | #define KW_I2C_STAT_LAST_AAK 0x02 | ||
40 | #define KW_I2C_STAT_LAST_RW 0x04 | ||
41 | #define KW_I2C_STAT_SDA 0x08 | ||
42 | #define KW_I2C_STAT_SCL 0x10 | ||
43 | |||
44 | /* IER & ISR registers */ | ||
45 | #define KW_I2C_IRQ_DATA 0x01 | ||
46 | #define KW_I2C_IRQ_ADDR 0x02 | ||
47 | #define KW_I2C_IRQ_STOP 0x04 | ||
48 | #define KW_I2C_IRQ_START 0x08 | ||
49 | #define KW_I2C_IRQ_MASK 0x0F | ||
50 | |||
51 | /* Physical interface */ | ||
52 | struct keywest_iface | ||
53 | { | ||
54 | struct device_node *node; | ||
55 | void __iomem * base; | ||
56 | unsigned bsteps; | ||
57 | int irq; | ||
58 | spinlock_t lock; | ||
59 | struct keywest_chan *channels; | ||
60 | unsigned chan_count; | ||
61 | u8 cur_mode; | ||
62 | char read_write; | ||
63 | u8 *data; | ||
64 | unsigned datalen; | ||
65 | int state; | ||
66 | int result; | ||
67 | struct timer_list timeout_timer; | ||
68 | struct completion complete; | ||
69 | }; | ||
70 | |||
71 | enum { | ||
72 | state_idle, | ||
73 | state_addr, | ||
74 | state_read, | ||
75 | state_write, | ||
76 | state_stop, | ||
77 | state_dead | ||
78 | }; | ||
79 | |||
80 | /* Channel on an interface */ | ||
81 | struct keywest_chan | ||
82 | { | ||
83 | struct i2c_adapter adapter; | ||
84 | struct keywest_iface* iface; | ||
85 | unsigned chan_no; | ||
86 | }; | ||
87 | |||
88 | /* Register access */ | ||
89 | |||
90 | static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg) | ||
91 | { | ||
92 | return in_8(iface->base | ||
93 | + (((unsigned)reg) << iface->bsteps)); | ||
94 | } | ||
95 | |||
96 | static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val) | ||
97 | { | ||
98 | out_8(iface->base | ||
99 | + (((unsigned)reg) << iface->bsteps), val); | ||
100 | (void)__read_reg(iface, reg_subaddr); | ||
101 | } | ||
102 | |||
103 | #define write_reg(reg, val) __write_reg(iface, reg, val) | ||
104 | #define read_reg(reg) __read_reg(iface, reg) | ||
105 | |||
106 | |||
107 | |||
108 | #endif /* __I2C_KEYWEST_H__ */ | ||
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 81031eb51056..22781d84f79f 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/i2c/busses/i2c-mv64xxx.c | ||
3 | * | ||
4 | * Driver for the i2c controller on the Marvell line of host bridges for MIPS | 2 | * Driver for the i2c controller on the Marvell line of host bridges for MIPS |
5 | * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0). | 3 | * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0). |
6 | * | 4 | * |
@@ -65,7 +63,6 @@ enum { | |||
65 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, | 63 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, |
66 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, | 64 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, |
67 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, | 65 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, |
68 | MV64XXX_I2C_STATE_ABORTING, | ||
69 | }; | 66 | }; |
70 | 67 | ||
71 | /* Driver actions */ | 68 | /* Driver actions */ |
@@ -85,6 +82,7 @@ struct mv64xxx_i2c_data { | |||
85 | int irq; | 82 | int irq; |
86 | u32 state; | 83 | u32 state; |
87 | u32 action; | 84 | u32 action; |
85 | u32 aborting; | ||
88 | u32 cntl_bits; | 86 | u32 cntl_bits; |
89 | void __iomem *reg_base; | 87 | void __iomem *reg_base; |
90 | u32 reg_base_p; | 88 | u32 reg_base_p; |
@@ -122,12 +120,6 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |||
122 | return; | 120 | return; |
123 | } | 121 | } |
124 | 122 | ||
125 | if (drv_data->state == MV64XXX_I2C_STATE_ABORTING) { | ||
126 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
127 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | /* The status from the ctlr [mostly] tells us what to do next */ | 123 | /* The status from the ctlr [mostly] tells us what to do next */ |
132 | switch (status) { | 124 | switch (status) { |
133 | /* Start condition interrupt */ | 125 | /* Start condition interrupt */ |
@@ -148,14 +140,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |||
148 | /* FALLTHRU */ | 140 | /* FALLTHRU */ |
149 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ | 141 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ |
150 | case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ | 142 | case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ |
151 | if (drv_data->bytes_left > 0) { | 143 | if ((drv_data->bytes_left == 0) |
144 | || (drv_data->aborting | ||
145 | && (drv_data->byte_posn != 0))) { | ||
146 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
147 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
148 | } else { | ||
152 | drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; | 149 | drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; |
153 | drv_data->state = | 150 | drv_data->state = |
154 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; | 151 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; |
155 | drv_data->bytes_left--; | 152 | drv_data->bytes_left--; |
156 | } else { | ||
157 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
158 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
159 | } | 153 | } |
160 | break; | 154 | break; |
161 | 155 | ||
@@ -184,7 +178,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |||
184 | } | 178 | } |
185 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; | 179 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; |
186 | 180 | ||
187 | if (drv_data->bytes_left == 1) | 181 | if ((drv_data->bytes_left == 1) || drv_data->aborting) |
188 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; | 182 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; |
189 | break; | 183 | break; |
190 | 184 | ||
@@ -320,6 +314,7 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, | |||
320 | drv_data->msg = msg; | 314 | drv_data->msg = msg; |
321 | drv_data->byte_posn = 0; | 315 | drv_data->byte_posn = 0; |
322 | drv_data->bytes_left = msg->len; | 316 | drv_data->bytes_left = msg->len; |
317 | drv_data->aborting = 0; | ||
323 | drv_data->rc = 0; | 318 | drv_data->rc = 0; |
324 | drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | | 319 | drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | |
325 | MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; | 320 | MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; |
@@ -359,17 +354,19 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) | |||
359 | } | 354 | } |
360 | 355 | ||
361 | if (abort && drv_data->block) { | 356 | if (abort && drv_data->block) { |
362 | drv_data->state = MV64XXX_I2C_STATE_ABORTING; | 357 | drv_data->aborting = 1; |
363 | spin_unlock_irqrestore(&drv_data->lock, flags); | 358 | spin_unlock_irqrestore(&drv_data->lock, flags); |
364 | 359 | ||
365 | time_left = wait_event_timeout(drv_data->waitq, | 360 | time_left = wait_event_timeout(drv_data->waitq, |
366 | !drv_data->block, | 361 | !drv_data->block, |
367 | msecs_to_jiffies(drv_data->adapter.timeout)); | 362 | msecs_to_jiffies(drv_data->adapter.timeout)); |
368 | 363 | ||
369 | if (time_left <= 0) { | 364 | if ((time_left <= 0) && drv_data->block) { |
370 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | 365 | drv_data->state = MV64XXX_I2C_STATE_IDLE; |
371 | dev_err(&drv_data->adapter.dev, | 366 | dev_err(&drv_data->adapter.dev, |
372 | "mv64xxx: I2C bus locked\n"); | 367 | "mv64xxx: I2C bus locked, block: %d, " |
368 | "time_left: %d\n", drv_data->block, | ||
369 | (int)time_left); | ||
373 | } | 370 | } |
374 | } else | 371 | } else |
375 | spin_unlock_irqrestore(&drv_data->lock, flags); | 372 | spin_unlock_irqrestore(&drv_data->lock, flags); |
@@ -510,7 +507,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
510 | goto exit_kfree; | 507 | goto exit_kfree; |
511 | } | 508 | } |
512 | 509 | ||
513 | strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", | 510 | strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", |
514 | I2C_NAME_SIZE); | 511 | I2C_NAME_SIZE); |
515 | 512 | ||
516 | init_waitqueue_head(&drv_data->waitq); | 513 | init_waitqueue_head(&drv_data->waitq); |
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 4d18e6e5f159..2d80eb26f688 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c | |||
@@ -30,6 +30,7 @@ | |||
30 | nForce3 Pro150 MCP 00D4 | 30 | nForce3 Pro150 MCP 00D4 |
31 | nForce3 250Gb MCP 00E4 | 31 | nForce3 250Gb MCP 00E4 |
32 | nForce4 MCP 0052 | 32 | nForce4 MCP 0052 |
33 | nForce4 MCP-04 0034 | ||
33 | 34 | ||
34 | This driver supports the 2 SMBuses that are included in the MCP of the | 35 | This driver supports the 2 SMBuses that are included in the MCP of the |
35 | nForce2/3/4 chipsets. | 36 | nForce2/3/4 chipsets. |
@@ -257,6 +258,7 @@ static struct pci_device_id nforce2_ids[] = { | |||
257 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, | 258 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, |
258 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, | 259 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, |
259 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) }, | 260 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) }, |
261 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, | ||
260 | { 0 } | 262 | { 0 } |
261 | }; | 263 | }; |
262 | 264 | ||
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h index f63a53779281..d702e5e0388d 100644 --- a/drivers/i2c/busses/i2c-parport.h +++ b/drivers/i2c/busses/i2c-parport.h | |||
@@ -80,6 +80,14 @@ static struct adapter_parm adapter_parm[] = { | |||
80 | .setscl = { 0x01, DATA, 1 }, | 80 | .setscl = { 0x01, DATA, 1 }, |
81 | .getsda = { 0x10, STAT, 1 }, | 81 | .getsda = { 0x10, STAT, 1 }, |
82 | }, | 82 | }, |
83 | /* type 6: Barco LPT->DVI (K5800236) adapter */ | ||
84 | { | ||
85 | .setsda = { 0x02, DATA, 1 }, | ||
86 | .setscl = { 0x01, DATA, 1 }, | ||
87 | .getsda = { 0x20, STAT, 0 }, | ||
88 | .getscl = { 0x40, STAT, 0 }, | ||
89 | .init = { 0xfc, DATA, 0 }, | ||
90 | }, | ||
83 | }; | 91 | }; |
84 | 92 | ||
85 | static int type; | 93 | static int type; |
@@ -91,4 +99,6 @@ MODULE_PARM_DESC(type, | |||
91 | " 2 = Velleman K8000 adapter\n" | 99 | " 2 = Velleman K8000 adapter\n" |
92 | " 3 = ELV adapter\n" | 100 | " 3 = ELV adapter\n" |
93 | " 4 = ADM1032 evaluation board\n" | 101 | " 4 = ADM1032 evaluation board\n" |
94 | " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"); | 102 | " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n" |
103 | " 6 = Barco LPT->DVI (K5800236) adapter\n" | ||
104 | ); | ||
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c deleted file mode 100644 index bfefe7f7a53d..000000000000 --- a/drivers/i2c/busses/i2c-pmac-smu.c +++ /dev/null | |||
@@ -1,315 +0,0 @@ | |||
1 | /* | ||
2 | i2c Support for Apple SMU Controller | ||
3 | |||
4 | Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp. | ||
5 | <benh@kernel.crashing.org> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/completion.h> | ||
30 | #include <linux/device.h> | ||
31 | #include <asm/prom.h> | ||
32 | #include <asm/of_device.h> | ||
33 | #include <asm/smu.h> | ||
34 | |||
35 | static int probe; | ||
36 | |||
37 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
38 | MODULE_DESCRIPTION("I2C driver for Apple's SMU"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | module_param(probe, bool, 0); | ||
41 | |||
42 | |||
43 | /* Physical interface */ | ||
44 | struct smu_iface | ||
45 | { | ||
46 | struct i2c_adapter adapter; | ||
47 | struct completion complete; | ||
48 | u32 busid; | ||
49 | }; | ||
50 | |||
51 | static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc) | ||
52 | { | ||
53 | struct smu_iface *iface = misc; | ||
54 | complete(&iface->complete); | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * SMBUS-type transfer entrypoint | ||
59 | */ | ||
60 | static s32 smu_smbus_xfer( struct i2c_adapter* adap, | ||
61 | u16 addr, | ||
62 | unsigned short flags, | ||
63 | char read_write, | ||
64 | u8 command, | ||
65 | int size, | ||
66 | union i2c_smbus_data* data) | ||
67 | { | ||
68 | struct smu_iface *iface = i2c_get_adapdata(adap); | ||
69 | struct smu_i2c_cmd cmd; | ||
70 | int rc = 0; | ||
71 | int read = (read_write == I2C_SMBUS_READ); | ||
72 | |||
73 | cmd.info.bus = iface->busid; | ||
74 | cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00); | ||
75 | |||
76 | /* Prepare datas & select mode */ | ||
77 | switch (size) { | ||
78 | case I2C_SMBUS_QUICK: | ||
79 | cmd.info.type = SMU_I2C_TRANSFER_SIMPLE; | ||
80 | cmd.info.datalen = 0; | ||
81 | break; | ||
82 | case I2C_SMBUS_BYTE: | ||
83 | cmd.info.type = SMU_I2C_TRANSFER_SIMPLE; | ||
84 | cmd.info.datalen = 1; | ||
85 | if (!read) | ||
86 | cmd.info.data[0] = data->byte; | ||
87 | break; | ||
88 | case I2C_SMBUS_BYTE_DATA: | ||
89 | cmd.info.type = SMU_I2C_TRANSFER_STDSUB; | ||
90 | cmd.info.datalen = 1; | ||
91 | cmd.info.sublen = 1; | ||
92 | cmd.info.subaddr[0] = command; | ||
93 | cmd.info.subaddr[1] = 0; | ||
94 | cmd.info.subaddr[2] = 0; | ||
95 | if (!read) | ||
96 | cmd.info.data[0] = data->byte; | ||
97 | break; | ||
98 | case I2C_SMBUS_WORD_DATA: | ||
99 | cmd.info.type = SMU_I2C_TRANSFER_STDSUB; | ||
100 | cmd.info.datalen = 2; | ||
101 | cmd.info.sublen = 1; | ||
102 | cmd.info.subaddr[0] = command; | ||
103 | cmd.info.subaddr[1] = 0; | ||
104 | cmd.info.subaddr[2] = 0; | ||
105 | if (!read) { | ||
106 | cmd.info.data[0] = data->byte & 0xff; | ||
107 | cmd.info.data[1] = (data->byte >> 8) & 0xff; | ||
108 | } | ||
109 | break; | ||
110 | /* Note that these are broken vs. the expected smbus API where | ||
111 | * on reads, the lenght is actually returned from the function, | ||
112 | * but I think the current API makes no sense and I don't want | ||
113 | * any driver that I haven't verified for correctness to go | ||
114 | * anywhere near a pmac i2c bus anyway ... | ||
115 | */ | ||
116 | case I2C_SMBUS_BLOCK_DATA: | ||
117 | cmd.info.type = SMU_I2C_TRANSFER_STDSUB; | ||
118 | cmd.info.datalen = data->block[0] + 1; | ||
119 | if (cmd.info.datalen > 6) | ||
120 | return -EINVAL; | ||
121 | if (!read) | ||
122 | memcpy(cmd.info.data, data->block, cmd.info.datalen); | ||
123 | cmd.info.sublen = 1; | ||
124 | cmd.info.subaddr[0] = command; | ||
125 | cmd.info.subaddr[1] = 0; | ||
126 | cmd.info.subaddr[2] = 0; | ||
127 | break; | ||
128 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
129 | cmd.info.type = SMU_I2C_TRANSFER_STDSUB; | ||
130 | cmd.info.datalen = data->block[0]; | ||
131 | if (cmd.info.datalen > 7) | ||
132 | return -EINVAL; | ||
133 | if (!read) | ||
134 | memcpy(cmd.info.data, &data->block[1], | ||
135 | cmd.info.datalen); | ||
136 | cmd.info.sublen = 1; | ||
137 | cmd.info.subaddr[0] = command; | ||
138 | cmd.info.subaddr[1] = 0; | ||
139 | cmd.info.subaddr[2] = 0; | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | /* Turn a standardsub read into a combined mode access */ | ||
147 | if (read_write == I2C_SMBUS_READ && | ||
148 | cmd.info.type == SMU_I2C_TRANSFER_STDSUB) | ||
149 | cmd.info.type = SMU_I2C_TRANSFER_COMBINED; | ||
150 | |||
151 | /* Finish filling command and submit it */ | ||
152 | cmd.done = smu_i2c_done; | ||
153 | cmd.misc = iface; | ||
154 | rc = smu_queue_i2c(&cmd); | ||
155 | if (rc < 0) | ||
156 | return rc; | ||
157 | wait_for_completion(&iface->complete); | ||
158 | rc = cmd.status; | ||
159 | |||
160 | if (!read || rc < 0) | ||
161 | return rc; | ||
162 | |||
163 | switch (size) { | ||
164 | case I2C_SMBUS_BYTE: | ||
165 | case I2C_SMBUS_BYTE_DATA: | ||
166 | data->byte = cmd.info.data[0]; | ||
167 | break; | ||
168 | case I2C_SMBUS_WORD_DATA: | ||
169 | data->word = ((u16)cmd.info.data[1]) << 8; | ||
170 | data->word |= cmd.info.data[0]; | ||
171 | break; | ||
172 | /* Note that these are broken vs. the expected smbus API where | ||
173 | * on reads, the lenght is actually returned from the function, | ||
174 | * but I think the current API makes no sense and I don't want | ||
175 | * any driver that I haven't verified for correctness to go | ||
176 | * anywhere near a pmac i2c bus anyway ... | ||
177 | */ | ||
178 | case I2C_SMBUS_BLOCK_DATA: | ||
179 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
180 | memcpy(&data->block[0], cmd.info.data, cmd.info.datalen); | ||
181 | break; | ||
182 | } | ||
183 | |||
184 | return rc; | ||
185 | } | ||
186 | |||
187 | static u32 | ||
188 | smu_smbus_func(struct i2c_adapter * adapter) | ||
189 | { | ||
190 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
191 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
192 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
193 | } | ||
194 | |||
195 | /* For now, we only handle combined mode (smbus) */ | ||
196 | static struct i2c_algorithm smu_algorithm = { | ||
197 | .smbus_xfer = smu_smbus_xfer, | ||
198 | .functionality = smu_smbus_func, | ||
199 | }; | ||
200 | |||
201 | static int create_iface(struct device_node *np, struct device *dev) | ||
202 | { | ||
203 | struct smu_iface* iface; | ||
204 | u32 *reg, busid; | ||
205 | int rc; | ||
206 | |||
207 | reg = (u32 *)get_property(np, "reg", NULL); | ||
208 | if (reg == NULL) { | ||
209 | printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n"); | ||
210 | return -ENXIO; | ||
211 | } | ||
212 | busid = *reg; | ||
213 | |||
214 | iface = kzalloc(sizeof(struct smu_iface), GFP_KERNEL); | ||
215 | if (iface == NULL) { | ||
216 | printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n"); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | init_completion(&iface->complete); | ||
220 | iface->busid = busid; | ||
221 | |||
222 | dev_set_drvdata(dev, iface); | ||
223 | |||
224 | sprintf(iface->adapter.name, "smu-i2c-%02x", busid); | ||
225 | iface->adapter.algo = &smu_algorithm; | ||
226 | iface->adapter.algo_data = NULL; | ||
227 | iface->adapter.client_register = NULL; | ||
228 | iface->adapter.client_unregister = NULL; | ||
229 | i2c_set_adapdata(&iface->adapter, iface); | ||
230 | iface->adapter.dev.parent = dev; | ||
231 | |||
232 | rc = i2c_add_adapter(&iface->adapter); | ||
233 | if (rc) { | ||
234 | printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration " | ||
235 | "failed\n", iface->adapter.name); | ||
236 | i2c_set_adapdata(&iface->adapter, NULL); | ||
237 | } | ||
238 | |||
239 | if (probe) { | ||
240 | unsigned char addr; | ||
241 | printk("Probe: "); | ||
242 | for (addr = 0x00; addr <= 0x7f; addr++) { | ||
243 | if (i2c_smbus_xfer(&iface->adapter,addr, | ||
244 | 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) | ||
245 | printk("%02x ", addr); | ||
246 | } | ||
247 | printk("\n"); | ||
248 | } | ||
249 | |||
250 | printk(KERN_INFO "SMU i2c bus %x registered\n", busid); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int dispose_iface(struct device *dev) | ||
256 | { | ||
257 | struct smu_iface *iface = dev_get_drvdata(dev); | ||
258 | int rc; | ||
259 | |||
260 | rc = i2c_del_adapter(&iface->adapter); | ||
261 | i2c_set_adapdata(&iface->adapter, NULL); | ||
262 | /* We aren't that prepared to deal with this... */ | ||
263 | if (rc) | ||
264 | printk("i2c-pmac-smu.c: Failed to remove bus %s !\n", | ||
265 | iface->adapter.name); | ||
266 | dev_set_drvdata(dev, NULL); | ||
267 | kfree(iface); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | |||
273 | static int create_iface_of_platform(struct of_device* dev, | ||
274 | const struct of_device_id *match) | ||
275 | { | ||
276 | return create_iface(dev->node, &dev->dev); | ||
277 | } | ||
278 | |||
279 | |||
280 | static int dispose_iface_of_platform(struct of_device* dev) | ||
281 | { | ||
282 | return dispose_iface(&dev->dev); | ||
283 | } | ||
284 | |||
285 | |||
286 | static struct of_device_id i2c_smu_match[] = | ||
287 | { | ||
288 | { | ||
289 | .compatible = "smu-i2c", | ||
290 | }, | ||
291 | {}, | ||
292 | }; | ||
293 | static struct of_platform_driver i2c_smu_of_platform_driver = | ||
294 | { | ||
295 | .name = "i2c-smu", | ||
296 | .match_table = i2c_smu_match, | ||
297 | .probe = create_iface_of_platform, | ||
298 | .remove = dispose_iface_of_platform | ||
299 | }; | ||
300 | |||
301 | |||
302 | static int __init i2c_pmac_smu_init(void) | ||
303 | { | ||
304 | of_register_driver(&i2c_smu_of_platform_driver); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | |||
309 | static void __exit i2c_pmac_smu_cleanup(void) | ||
310 | { | ||
311 | of_unregister_driver(&i2c_smu_of_platform_driver); | ||
312 | } | ||
313 | |||
314 | module_init(i2c_pmac_smu_init); | ||
315 | module_exit(i2c_pmac_smu_cleanup); | ||
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c new file mode 100644 index 000000000000..df786eb55295 --- /dev/null +++ b/drivers/i2c/busses/i2c-powermac.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | i2c Support for Apple SMU Controller | ||
3 | |||
4 | Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp. | ||
5 | <benh@kernel.crashing.org> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/completion.h> | ||
30 | #include <linux/device.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <asm/prom.h> | ||
33 | #include <asm/pmac_low_i2c.h> | ||
34 | |||
35 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
36 | MODULE_DESCRIPTION("I2C driver for Apple PowerMac"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | /* | ||
40 | * SMBUS-type transfer entrypoint | ||
41 | */ | ||
42 | static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, | ||
43 | u16 addr, | ||
44 | unsigned short flags, | ||
45 | char read_write, | ||
46 | u8 command, | ||
47 | int size, | ||
48 | union i2c_smbus_data* data) | ||
49 | { | ||
50 | struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); | ||
51 | int rc = 0; | ||
52 | int read = (read_write == I2C_SMBUS_READ); | ||
53 | int addrdir = (addr << 1) | read; | ||
54 | u8 local[2]; | ||
55 | |||
56 | rc = pmac_i2c_open(bus, 0); | ||
57 | if (rc) | ||
58 | return rc; | ||
59 | |||
60 | switch (size) { | ||
61 | case I2C_SMBUS_QUICK: | ||
62 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
63 | if (rc) | ||
64 | goto bail; | ||
65 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0); | ||
66 | break; | ||
67 | case I2C_SMBUS_BYTE: | ||
68 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
69 | if (rc) | ||
70 | goto bail; | ||
71 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1); | ||
72 | break; | ||
73 | case I2C_SMBUS_BYTE_DATA: | ||
74 | rc = pmac_i2c_setmode(bus, read ? | ||
75 | pmac_i2c_mode_combined : | ||
76 | pmac_i2c_mode_stdsub); | ||
77 | if (rc) | ||
78 | goto bail; | ||
79 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1); | ||
80 | break; | ||
81 | case I2C_SMBUS_WORD_DATA: | ||
82 | rc = pmac_i2c_setmode(bus, read ? | ||
83 | pmac_i2c_mode_combined : | ||
84 | pmac_i2c_mode_stdsub); | ||
85 | if (rc) | ||
86 | goto bail; | ||
87 | if (!read) { | ||
88 | local[0] = data->word & 0xff; | ||
89 | local[1] = (data->word >> 8) & 0xff; | ||
90 | } | ||
91 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2); | ||
92 | if (rc == 0 && read) { | ||
93 | data->word = ((u16)local[1]) << 8; | ||
94 | data->word |= local[0]; | ||
95 | } | ||
96 | break; | ||
97 | |||
98 | /* Note that these are broken vs. the expected smbus API where | ||
99 | * on reads, the lenght is actually returned from the function, | ||
100 | * but I think the current API makes no sense and I don't want | ||
101 | * any driver that I haven't verified for correctness to go | ||
102 | * anywhere near a pmac i2c bus anyway ... | ||
103 | * | ||
104 | * I'm also not completely sure what kind of phases to do between | ||
105 | * the actual command and the data (what I am _supposed_ to do that | ||
106 | * is). For now, I assume writes are a single stream and reads have | ||
107 | * a repeat start/addr phase (but not stop in between) | ||
108 | */ | ||
109 | case I2C_SMBUS_BLOCK_DATA: | ||
110 | rc = pmac_i2c_setmode(bus, read ? | ||
111 | pmac_i2c_mode_combined : | ||
112 | pmac_i2c_mode_stdsub); | ||
113 | if (rc) | ||
114 | goto bail; | ||
115 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block, | ||
116 | data->block[0] + 1); | ||
117 | |||
118 | break; | ||
119 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
120 | rc = pmac_i2c_setmode(bus, read ? | ||
121 | pmac_i2c_mode_combined : | ||
122 | pmac_i2c_mode_stdsub); | ||
123 | if (rc) | ||
124 | goto bail; | ||
125 | rc = pmac_i2c_xfer(bus, addrdir, 1, command, | ||
126 | read ? data->block : &data->block[1], | ||
127 | data->block[0]); | ||
128 | break; | ||
129 | |||
130 | default: | ||
131 | rc = -EINVAL; | ||
132 | } | ||
133 | bail: | ||
134 | pmac_i2c_close(bus); | ||
135 | return rc; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Generic i2c master transfer entrypoint. This driver only support single | ||
140 | * messages (for "lame i2c" transfers). Anything else should use the smbus | ||
141 | * entry point | ||
142 | */ | ||
143 | static int i2c_powermac_master_xfer( struct i2c_adapter *adap, | ||
144 | struct i2c_msg *msgs, | ||
145 | int num) | ||
146 | { | ||
147 | struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); | ||
148 | int rc = 0; | ||
149 | int read; | ||
150 | int addrdir; | ||
151 | |||
152 | if (num != 1) | ||
153 | return -EINVAL; | ||
154 | if (msgs->flags & I2C_M_TEN) | ||
155 | return -EINVAL; | ||
156 | read = (msgs->flags & I2C_M_RD) != 0; | ||
157 | addrdir = (msgs->addr << 1) | read; | ||
158 | if (msgs->flags & I2C_M_REV_DIR_ADDR) | ||
159 | addrdir ^= 1; | ||
160 | |||
161 | rc = pmac_i2c_open(bus, 0); | ||
162 | if (rc) | ||
163 | return rc; | ||
164 | rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); | ||
165 | if (rc) | ||
166 | goto bail; | ||
167 | rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); | ||
168 | bail: | ||
169 | pmac_i2c_close(bus); | ||
170 | return rc < 0 ? rc : msgs->len; | ||
171 | } | ||
172 | |||
173 | static u32 i2c_powermac_func(struct i2c_adapter * adapter) | ||
174 | { | ||
175 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
176 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
177 | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C; | ||
178 | } | ||
179 | |||
180 | /* For now, we only handle smbus */ | ||
181 | static struct i2c_algorithm i2c_powermac_algorithm = { | ||
182 | .smbus_xfer = i2c_powermac_smbus_xfer, | ||
183 | .master_xfer = i2c_powermac_master_xfer, | ||
184 | .functionality = i2c_powermac_func, | ||
185 | }; | ||
186 | |||
187 | |||
188 | static int i2c_powermac_remove(struct device *dev) | ||
189 | { | ||
190 | struct i2c_adapter *adapter = dev_get_drvdata(dev); | ||
191 | struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter); | ||
192 | int rc; | ||
193 | |||
194 | rc = i2c_del_adapter(adapter); | ||
195 | pmac_i2c_detach_adapter(bus, adapter); | ||
196 | i2c_set_adapdata(adapter, NULL); | ||
197 | /* We aren't that prepared to deal with this... */ | ||
198 | if (rc) | ||
199 | printk("i2c-powermac.c: Failed to remove bus %s !\n", | ||
200 | adapter->name); | ||
201 | dev_set_drvdata(dev, NULL); | ||
202 | kfree(adapter); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | |||
208 | static int i2c_powermac_probe(struct device *dev) | ||
209 | { | ||
210 | struct pmac_i2c_bus *bus = dev->platform_data; | ||
211 | struct device_node *parent = NULL; | ||
212 | struct i2c_adapter *adapter; | ||
213 | char name[32], *basename; | ||
214 | int rc; | ||
215 | |||
216 | if (bus == NULL) | ||
217 | return -EINVAL; | ||
218 | |||
219 | /* Ok, now we need to make up a name for the interface that will | ||
220 | * match what we used to do in the past, that is basically the | ||
221 | * controller's parent device node for keywest. PMU didn't have a | ||
222 | * naming convention and SMU has a different one | ||
223 | */ | ||
224 | switch(pmac_i2c_get_type(bus)) { | ||
225 | case pmac_i2c_bus_keywest: | ||
226 | parent = of_get_parent(pmac_i2c_get_controller(bus)); | ||
227 | if (parent == NULL) | ||
228 | return -EINVAL; | ||
229 | basename = parent->name; | ||
230 | break; | ||
231 | case pmac_i2c_bus_pmu: | ||
232 | basename = "pmu"; | ||
233 | break; | ||
234 | case pmac_i2c_bus_smu: | ||
235 | /* This is not what we used to do but I'm fixing drivers at | ||
236 | * the same time as this change | ||
237 | */ | ||
238 | basename = "smu"; | ||
239 | break; | ||
240 | default: | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus)); | ||
244 | of_node_put(parent); | ||
245 | |||
246 | adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); | ||
247 | if (adapter == NULL) { | ||
248 | printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n"); | ||
249 | return -ENOMEM; | ||
250 | } | ||
251 | dev_set_drvdata(dev, adapter); | ||
252 | strcpy(adapter->name, name); | ||
253 | adapter->algo = &i2c_powermac_algorithm; | ||
254 | i2c_set_adapdata(adapter, bus); | ||
255 | adapter->dev.parent = dev; | ||
256 | pmac_i2c_attach_adapter(bus, adapter); | ||
257 | rc = i2c_add_adapter(adapter); | ||
258 | if (rc) { | ||
259 | printk(KERN_ERR "i2c-powermac: Adapter %s registration " | ||
260 | "failed\n", name); | ||
261 | i2c_set_adapdata(adapter, NULL); | ||
262 | pmac_i2c_detach_adapter(bus, adapter); | ||
263 | } | ||
264 | |||
265 | printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); | ||
266 | return rc; | ||
267 | } | ||
268 | |||
269 | |||
270 | static struct device_driver i2c_powermac_driver = { | ||
271 | .name = "i2c-powermac", | ||
272 | .bus = &platform_bus_type, | ||
273 | .probe = i2c_powermac_probe, | ||
274 | .remove = i2c_powermac_remove, | ||
275 | }; | ||
276 | |||
277 | static int __init i2c_powermac_init(void) | ||
278 | { | ||
279 | driver_register(&i2c_powermac_driver); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | static void __exit i2c_powermac_cleanup(void) | ||
285 | { | ||
286 | driver_unregister(&i2c_powermac_driver); | ||
287 | } | ||
288 | |||
289 | module_init(i2c_powermac_init); | ||
290 | module_exit(i2c_powermac_cleanup); | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 70f7ab829d36..86e2234faf80 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -899,6 +899,12 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num | |||
899 | struct pxa_i2c *i2c = adap->algo_data; | 899 | struct pxa_i2c *i2c = adap->algo_data; |
900 | int ret, i; | 900 | int ret, i; |
901 | 901 | ||
902 | /* If the I2C controller is disabled we need to reset it (probably due | ||
903 | to a suspend/resume destroying state). We do this here as we can then | ||
904 | avoid worrying about resuming the controller before its users. */ | ||
905 | if (!(ICR & ICR_IUE)) | ||
906 | i2c_pxa_reset(i2c); | ||
907 | |||
902 | for (i = adap->retries; i >= 0; i--) { | 908 | for (i = adap->retries; i >= 0; i--) { |
903 | ret = i2c_pxa_do_xfer(i2c, msgs, num); | 909 | ret = i2c_pxa_do_xfer(i2c, msgs, num); |
904 | if (ret != I2C_RETRY) | 910 | if (ret != I2C_RETRY) |
@@ -939,7 +945,9 @@ static struct pxa_i2c i2c_pxa = { | |||
939 | static int i2c_pxa_probe(struct platform_device *dev) | 945 | static int i2c_pxa_probe(struct platform_device *dev) |
940 | { | 946 | { |
941 | struct pxa_i2c *i2c = &i2c_pxa; | 947 | struct pxa_i2c *i2c = &i2c_pxa; |
948 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
942 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 949 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; |
950 | #endif | ||
943 | int ret; | 951 | int ret; |
944 | 952 | ||
945 | #ifdef CONFIG_PXA27x | 953 | #ifdef CONFIG_PXA27x |
@@ -1024,5 +1032,7 @@ static void i2c_adap_pxa_exit(void) | |||
1024 | return platform_driver_unregister(&i2c_pxa_driver); | 1032 | return platform_driver_unregister(&i2c_pxa_driver); |
1025 | } | 1033 | } |
1026 | 1034 | ||
1035 | MODULE_LICENSE("GPL"); | ||
1036 | |||
1027 | module_init(i2c_adap_pxa_init); | 1037 | module_init(i2c_adap_pxa_init); |
1028 | module_exit(i2c_adap_pxa_exit); | 1038 | module_exit(i2c_adap_pxa_exit); |
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 58cfd3111ef6..f7d40f8e5f5c 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -34,12 +34,12 @@ | |||
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/clk.h> | ||
37 | 38 | ||
38 | #include <asm/hardware.h> | 39 | #include <asm/hardware.h> |
39 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | 42 | ||
42 | #include <asm/hardware/clock.h> | ||
43 | #include <asm/arch/regs-gpio.h> | 43 | #include <asm/arch/regs-gpio.h> |
44 | #include <asm/arch/regs-iic.h> | 44 | #include <asm/arch/regs-iic.h> |
45 | #include <asm/arch/iic.h> | 45 | #include <asm/arch/iic.h> |
@@ -738,7 +738,6 @@ static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c) | |||
738 | { | 738 | { |
739 | if (i2c->clk != NULL && !IS_ERR(i2c->clk)) { | 739 | if (i2c->clk != NULL && !IS_ERR(i2c->clk)) { |
740 | clk_disable(i2c->clk); | 740 | clk_disable(i2c->clk); |
741 | clk_unuse(i2c->clk); | ||
742 | clk_put(i2c->clk); | 741 | clk_put(i2c->clk); |
743 | i2c->clk = NULL; | 742 | i2c->clk = NULL; |
744 | } | 743 | } |
@@ -778,7 +777,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
778 | 777 | ||
779 | dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); | 778 | dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); |
780 | 779 | ||
781 | clk_use(i2c->clk); | ||
782 | clk_enable(i2c->clk); | 780 | clk_enable(i2c->clk); |
783 | 781 | ||
784 | /* map the registers */ | 782 | /* map the registers */ |
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 02682fb794c8..93d483b8b770 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c | |||
@@ -52,9 +52,9 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd, | |||
52 | * Driver data (common to all clients) | 52 | * Driver data (common to all clients) |
53 | */ | 53 | */ |
54 | static struct i2c_driver ds1337_driver = { | 54 | static struct i2c_driver ds1337_driver = { |
55 | .owner = THIS_MODULE, | 55 | .driver = { |
56 | .name = "ds1337", | 56 | .name = "ds1337", |
57 | .flags = I2C_DF_NOTIFY, | 57 | }, |
58 | .attach_adapter = ds1337_attach_adapter, | 58 | .attach_adapter = ds1337_attach_adapter, |
59 | .detach_client = ds1337_detach_client, | 59 | .detach_client = ds1337_detach_client, |
60 | .command = ds1337_command, | 60 | .command = ds1337_command, |
@@ -337,13 +337,38 @@ exit: | |||
337 | 337 | ||
338 | static void ds1337_init_client(struct i2c_client *client) | 338 | static void ds1337_init_client(struct i2c_client *client) |
339 | { | 339 | { |
340 | s32 val; | 340 | u8 status, control; |
341 | 341 | ||
342 | /* Ensure that device is set in 24-hour mode */ | 342 | /* On some boards, the RTC isn't configured by boot firmware. |
343 | val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); | 343 | * Handle that case by starting/configuring the RTC now. |
344 | if ((val >= 0) && (val & (1 << 6))) | 344 | */ |
345 | i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, | 345 | status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); |
346 | val & 0x3f); | 346 | control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); |
347 | |||
348 | if ((status & 0x80) || (control & 0x80)) { | ||
349 | /* RTC not running */ | ||
350 | u8 buf[16]; | ||
351 | struct i2c_msg msg[1]; | ||
352 | |||
353 | dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__); | ||
354 | |||
355 | /* Initialize all, including STATUS and CONTROL to zero */ | ||
356 | memset(buf, 0, sizeof(buf)); | ||
357 | msg[0].addr = client->addr; | ||
358 | msg[0].flags = 0; | ||
359 | msg[0].len = sizeof(buf); | ||
360 | msg[0].buf = &buf[0]; | ||
361 | |||
362 | i2c_transfer(client->adapter, msg, 1); | ||
363 | } else { | ||
364 | /* Running: ensure that device is set in 24-hour mode */ | ||
365 | s32 val; | ||
366 | |||
367 | val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); | ||
368 | if ((val >= 0) && (val & (1 << 6))) | ||
369 | i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, | ||
370 | val & 0x3f); | ||
371 | } | ||
347 | } | 372 | } |
348 | 373 | ||
349 | static int ds1337_detach_client(struct i2c_client *client) | 374 | static int ds1337_detach_client(struct i2c_client *client) |
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c index da488b735abf..0710b9da9d54 100644 --- a/drivers/i2c/chips/ds1374.c +++ b/drivers/i2c/chips/ds1374.c | |||
@@ -232,10 +232,10 @@ static int ds1374_detach(struct i2c_client *client) | |||
232 | } | 232 | } |
233 | 233 | ||
234 | static struct i2c_driver ds1374_driver = { | 234 | static struct i2c_driver ds1374_driver = { |
235 | .owner = THIS_MODULE, | 235 | .driver = { |
236 | .name = DS1374_DRV_NAME, | 236 | .name = DS1374_DRV_NAME, |
237 | }, | ||
237 | .id = I2C_DRIVERID_DS1374, | 238 | .id = I2C_DRIVERID_DS1374, |
238 | .flags = I2C_DF_NOTIFY, | ||
239 | .attach_adapter = ds1374_attach, | 239 | .attach_adapter = ds1374_attach, |
240 | .detach_client = ds1374_detach, | 240 | .detach_client = ds1374_detach, |
241 | }; | 241 | }; |
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 4baf573fa04f..41116b7947f6 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c | |||
@@ -68,10 +68,10 @@ static int eeprom_detach_client(struct i2c_client *client); | |||
68 | 68 | ||
69 | /* This is the driver that will be inserted */ | 69 | /* This is the driver that will be inserted */ |
70 | static struct i2c_driver eeprom_driver = { | 70 | static struct i2c_driver eeprom_driver = { |
71 | .owner = THIS_MODULE, | 71 | .driver = { |
72 | .name = "eeprom", | 72 | .name = "eeprom", |
73 | }, | ||
73 | .id = I2C_DRIVERID_EEPROM, | 74 | .id = I2C_DRIVERID_EEPROM, |
74 | .flags = I2C_DF_NOTIFY, | ||
75 | .attach_adapter = eeprom_attach_adapter, | 75 | .attach_adapter = eeprom_attach_adapter, |
76 | .detach_client = eeprom_detach_client, | 76 | .detach_client = eeprom_detach_client, |
77 | }; | 77 | }; |
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index d2a100d77839..1251c7fc18d5 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c | |||
@@ -1632,11 +1632,11 @@ static int isp1301_scan_bus(struct i2c_adapter *bus) | |||
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | static struct i2c_driver isp1301_driver = { | 1634 | static struct i2c_driver isp1301_driver = { |
1635 | .owner = THIS_MODULE, | 1635 | .driver = { |
1636 | .name = "isp1301_omap", | 1636 | .name = "isp1301_omap", |
1637 | }, | ||
1637 | .id = 1301, /* FIXME "official", i2c-ids.h */ | 1638 | .id = 1301, /* FIXME "official", i2c-ids.h */ |
1638 | .class = I2C_CLASS_HWMON, | 1639 | .class = I2C_CLASS_HWMON, |
1639 | .flags = I2C_DF_NOTIFY, | ||
1640 | .attach_adapter = isp1301_scan_bus, | 1640 | .attach_adapter = isp1301_scan_bus, |
1641 | .detach_client = isp1301_detach_client, | 1641 | .detach_client = isp1301_detach_client, |
1642 | }; | 1642 | }; |
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index 3df309ae44a6..2dc3d48375fc 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c | |||
@@ -211,10 +211,10 @@ m41t00_detach(struct i2c_client *client) | |||
211 | } | 211 | } |
212 | 212 | ||
213 | static struct i2c_driver m41t00_driver = { | 213 | static struct i2c_driver m41t00_driver = { |
214 | .owner = THIS_MODULE, | 214 | .driver = { |
215 | .name = M41T00_DRV_NAME, | 215 | .name = M41T00_DRV_NAME, |
216 | }, | ||
216 | .id = I2C_DRIVERID_STM41T00, | 217 | .id = I2C_DRIVERID_STM41T00, |
217 | .flags = I2C_DF_NOTIFY, | ||
218 | .attach_adapter = m41t00_attach, | 218 | .attach_adapter = m41t00_attach, |
219 | .detach_client = m41t00_detach, | 219 | .detach_client = m41t00_detach, |
220 | }; | 220 | }; |
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index b376a006883c..6d3ff584155e 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c | |||
@@ -67,9 +67,9 @@ static int max6875_detach_client(struct i2c_client *client); | |||
67 | 67 | ||
68 | /* This is the driver that will be inserted */ | 68 | /* This is the driver that will be inserted */ |
69 | static struct i2c_driver max6875_driver = { | 69 | static struct i2c_driver max6875_driver = { |
70 | .owner = THIS_MODULE, | 70 | .driver = { |
71 | .name = "max6875", | 71 | .name = "max6875", |
72 | .flags = I2C_DF_NOTIFY, | 72 | }, |
73 | .attach_adapter = max6875_attach_adapter, | 73 | .attach_adapter = max6875_attach_adapter, |
74 | .detach_client = max6875_detach_client, | 74 | .detach_client = max6875_detach_client, |
75 | }; | 75 | }; |
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c index 59a930346229..54b6e6a4beed 100644 --- a/drivers/i2c/chips/pca9539.c +++ b/drivers/i2c/chips/pca9539.c | |||
@@ -38,9 +38,9 @@ static int pca9539_detach_client(struct i2c_client *client); | |||
38 | 38 | ||
39 | /* This is the driver that will be inserted */ | 39 | /* This is the driver that will be inserted */ |
40 | static struct i2c_driver pca9539_driver = { | 40 | static struct i2c_driver pca9539_driver = { |
41 | .owner = THIS_MODULE, | 41 | .driver = { |
42 | .name = "pca9539", | 42 | .name = "pca9539", |
43 | .flags = I2C_DF_NOTIFY, | 43 | }, |
44 | .attach_adapter = pca9539_attach_adapter, | 44 | .attach_adapter = pca9539_attach_adapter, |
45 | .detach_client = pca9539_detach_client, | 45 | .detach_client = pca9539_detach_client, |
46 | }; | 46 | }; |
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c index c323c2de236c..c3e6449c4481 100644 --- a/drivers/i2c/chips/pcf8574.c +++ b/drivers/i2c/chips/pcf8574.c | |||
@@ -65,10 +65,10 @@ static void pcf8574_init_client(struct i2c_client *client); | |||
65 | 65 | ||
66 | /* This is the driver that will be inserted */ | 66 | /* This is the driver that will be inserted */ |
67 | static struct i2c_driver pcf8574_driver = { | 67 | static struct i2c_driver pcf8574_driver = { |
68 | .owner = THIS_MODULE, | 68 | .driver = { |
69 | .name = "pcf8574", | 69 | .name = "pcf8574", |
70 | }, | ||
70 | .id = I2C_DRIVERID_PCF8574, | 71 | .id = I2C_DRIVERID_PCF8574, |
71 | .flags = I2C_DF_NOTIFY, | ||
72 | .attach_adapter = pcf8574_attach_adapter, | 72 | .attach_adapter = pcf8574_attach_adapter, |
73 | .detach_client = pcf8574_detach_client, | 73 | .detach_client = pcf8574_detach_client, |
74 | }; | 74 | }; |
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index ce420a67560b..36cff09c678d 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c | |||
@@ -88,10 +88,10 @@ static int pcf8591_read_channel(struct device *dev, int channel); | |||
88 | 88 | ||
89 | /* This is the driver that will be inserted */ | 89 | /* This is the driver that will be inserted */ |
90 | static struct i2c_driver pcf8591_driver = { | 90 | static struct i2c_driver pcf8591_driver = { |
91 | .owner = THIS_MODULE, | 91 | .driver = { |
92 | .name = "pcf8591", | 92 | .name = "pcf8591", |
93 | }, | ||
93 | .id = I2C_DRIVERID_PCF8591, | 94 | .id = I2C_DRIVERID_PCF8591, |
94 | .flags = I2C_DF_NOTIFY, | ||
95 | .attach_adapter = pcf8591_attach_adapter, | 95 | .attach_adapter = pcf8591_attach_adapter, |
96 | .detach_client = pcf8591_detach_client, | 96 | .detach_client = pcf8591_detach_client, |
97 | }; | 97 | }; |
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c index 916cdc1af23c..ceaa6b0bdfd6 100644 --- a/drivers/i2c/chips/rtc8564.c +++ b/drivers/i2c/chips/rtc8564.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/bcd.h> | ||
17 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | #include <linux/string.h> | 20 | #include <linux/string.h> |
@@ -52,9 +53,6 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client) | |||
52 | #define CTRL1(c) _rtc8564_ctrl1(c) | 53 | #define CTRL1(c) _rtc8564_ctrl1(c) |
53 | #define CTRL2(c) _rtc8564_ctrl2(c) | 54 | #define CTRL2(c) _rtc8564_ctrl2(c) |
54 | 55 | ||
55 | #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) | ||
56 | #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) | ||
57 | |||
58 | static int debug;; | 56 | static int debug;; |
59 | module_param(debug, int, S_IRUGO | S_IWUSR); | 57 | module_param(debug, int, S_IRUGO | S_IWUSR); |
60 | 58 | ||
@@ -157,7 +155,6 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind) | |||
157 | 155 | ||
158 | strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); | 156 | strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); |
159 | i2c_set_clientdata(new_client, d); | 157 | i2c_set_clientdata(new_client, d); |
160 | new_client->flags = I2C_CLIENT_ALLOW_USE; | ||
161 | new_client->addr = addr; | 158 | new_client->addr = addr; |
162 | new_client->adapter = adap; | 159 | new_client->adapter = adap; |
163 | new_client->driver = &rtc8564_driver; | 160 | new_client->driver = &rtc8564_driver; |
@@ -224,16 +221,16 @@ static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt) | |||
224 | return ret; | 221 | return ret; |
225 | 222 | ||
226 | /* century stored in minute alarm reg */ | 223 | /* century stored in minute alarm reg */ |
227 | dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]); | 224 | dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]); |
228 | dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); | 225 | dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); |
229 | dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f); | 226 | dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f); |
230 | dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7); | 227 | dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7); |
231 | dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); | 228 | dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); |
232 | 229 | ||
233 | dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f); | 230 | dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f); |
234 | dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; | 231 | dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; |
235 | dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f); | 232 | dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f); |
236 | dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f); | 233 | dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f); |
237 | 234 | ||
238 | _DBGRTCTM(2, *dt); | 235 | _DBGRTCTM(2, *dt); |
239 | 236 | ||
@@ -255,18 +252,18 @@ rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) | |||
255 | 252 | ||
256 | buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; | 253 | buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; |
257 | buf[RTC8564_REG_CTRL2] = CTRL2(client); | 254 | buf[RTC8564_REG_CTRL2] = CTRL2(client); |
258 | buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs); | 255 | buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs); |
259 | buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins); | 256 | buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins); |
260 | buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours); | 257 | buf[RTC8564_REG_HR] = BIN2BCD(dt->hours); |
261 | 258 | ||
262 | if (datetoo) { | 259 | if (datetoo) { |
263 | len += 5; | 260 | len += 5; |
264 | buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday); | 261 | buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday); |
265 | buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday); | 262 | buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday); |
266 | buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f; | 263 | buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f; |
267 | /* century stored in minute alarm reg */ | 264 | /* century stored in minute alarm reg */ |
268 | buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100); | 265 | buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100); |
269 | buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100); | 266 | buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100); |
270 | } | 267 | } |
271 | 268 | ||
272 | ret = rtc8564_write(client, 0, buf, len); | 269 | ret = rtc8564_write(client, 0, buf, len); |
@@ -361,10 +358,10 @@ rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
361 | } | 358 | } |
362 | 359 | ||
363 | static struct i2c_driver rtc8564_driver = { | 360 | static struct i2c_driver rtc8564_driver = { |
364 | .owner = THIS_MODULE, | 361 | .driver = { |
365 | .name = "RTC8564", | 362 | .name = "RTC8564", |
363 | }, | ||
366 | .id = I2C_DRIVERID_RTC8564, | 364 | .id = I2C_DRIVERID_RTC8564, |
367 | .flags = I2C_DF_NOTIFY, | ||
368 | .attach_adapter = rtc8564_probe, | 365 | .attach_adapter = rtc8564_probe, |
369 | .detach_client = rtc8564_detach, | 366 | .detach_client = rtc8564_detach, |
370 | .command = rtc8564_command | 367 | .command = rtc8564_command |
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index 280dd7a45db6..1af3dfbb8086 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c | |||
@@ -494,6 +494,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
494 | { | 494 | { |
495 | struct tps65010 *tps; | 495 | struct tps65010 *tps; |
496 | int status; | 496 | int status; |
497 | unsigned long irqflags; | ||
497 | 498 | ||
498 | if (the_tps) { | 499 | if (the_tps) { |
499 | dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME); | 500 | dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME); |
@@ -520,13 +521,14 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
520 | } | 521 | } |
521 | 522 | ||
522 | #ifdef CONFIG_ARM | 523 | #ifdef CONFIG_ARM |
524 | irqflags = SA_SAMPLE_RANDOM | SA_TRIGGER_LOW; | ||
523 | if (machine_is_omap_h2()) { | 525 | if (machine_is_omap_h2()) { |
524 | tps->model = TPS65010; | 526 | tps->model = TPS65010; |
525 | omap_cfg_reg(W4_GPIO58); | 527 | omap_cfg_reg(W4_GPIO58); |
526 | tps->irq = OMAP_GPIO_IRQ(58); | 528 | tps->irq = OMAP_GPIO_IRQ(58); |
527 | omap_request_gpio(58); | 529 | omap_request_gpio(58); |
528 | omap_set_gpio_direction(58, 1); | 530 | omap_set_gpio_direction(58, 1); |
529 | set_irq_type(tps->irq, IRQT_FALLING); | 531 | irqflags |= SA_TRIGGER_FALLING; |
530 | } | 532 | } |
531 | if (machine_is_omap_osk()) { | 533 | if (machine_is_omap_osk()) { |
532 | tps->model = TPS65010; | 534 | tps->model = TPS65010; |
@@ -534,7 +536,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
534 | tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)); | 536 | tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)); |
535 | omap_request_gpio(OMAP_MPUIO(1)); | 537 | omap_request_gpio(OMAP_MPUIO(1)); |
536 | omap_set_gpio_direction(OMAP_MPUIO(1), 1); | 538 | omap_set_gpio_direction(OMAP_MPUIO(1), 1); |
537 | set_irq_type(tps->irq, IRQT_FALLING); | 539 | irqflags |= SA_TRIGGER_FALLING; |
538 | } | 540 | } |
539 | if (machine_is_omap_h3()) { | 541 | if (machine_is_omap_h3()) { |
540 | tps->model = TPS65013; | 542 | tps->model = TPS65013; |
@@ -542,13 +544,12 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
542 | // FIXME set up this board's IRQ ... | 544 | // FIXME set up this board's IRQ ... |
543 | } | 545 | } |
544 | #else | 546 | #else |
545 | #define set_irq_type(num,trigger) do{}while(0) | 547 | irqflags = SA_SAMPLE_RANDOM; |
546 | #endif | 548 | #endif |
547 | 549 | ||
548 | if (tps->irq > 0) { | 550 | if (tps->irq > 0) { |
549 | set_irq_type(tps->irq, IRQT_LOW); | ||
550 | status = request_irq(tps->irq, tps65010_irq, | 551 | status = request_irq(tps->irq, tps65010_irq, |
551 | SA_SAMPLE_RANDOM, DRIVER_NAME, tps); | 552 | irqflags, DRIVER_NAME, tps); |
552 | if (status < 0) { | 553 | if (status < 0) { |
553 | dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n", | 554 | dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n", |
554 | tps->irq, status); | 555 | tps->irq, status); |
@@ -637,9 +638,9 @@ static int __init tps65010_scan_bus(struct i2c_adapter *bus) | |||
637 | } | 638 | } |
638 | 639 | ||
639 | static struct i2c_driver tps65010_driver = { | 640 | static struct i2c_driver tps65010_driver = { |
640 | .owner = THIS_MODULE, | 641 | .driver = { |
641 | .name = "tps65010", | 642 | .name = "tps65010", |
642 | .flags = I2C_DF_NOTIFY, | 643 | }, |
643 | .attach_adapter = tps65010_scan_bus, | 644 | .attach_adapter = tps65010_scan_bus, |
644 | .detach_client = __exit_p(tps65010_detach_client), | 645 | .detach_client = __exit_p(tps65010_detach_client), |
645 | }; | 646 | }; |
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c index 7da366cdc18c..245fffa92dbd 100644 --- a/drivers/i2c/chips/x1205.c +++ b/drivers/i2c/chips/x1205.c | |||
@@ -105,9 +105,9 @@ static int x1205_command(struct i2c_client *client, unsigned int cmd, | |||
105 | void *arg); | 105 | void *arg); |
106 | 106 | ||
107 | static struct i2c_driver x1205_driver = { | 107 | static struct i2c_driver x1205_driver = { |
108 | .owner = THIS_MODULE, | 108 | .driver = { |
109 | .name = "x1205", | 109 | .name = "x1205", |
110 | .flags = I2C_DF_NOTIFY, | 110 | }, |
111 | .attach_adapter = &x1205_attach, | 111 | .attach_adapter = &x1205_attach, |
112 | .detach_client = &x1205_detach, | 112 | .detach_client = &x1205_detach, |
113 | }; | 113 | }; |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 82ea1b7ec914..0ce58b506046 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev) | |||
63 | return rc; | 63 | return rc; |
64 | } | 64 | } |
65 | 65 | ||
66 | struct bus_type i2c_bus_type = { | ||
67 | .name = "i2c", | ||
68 | .match = i2c_device_match, | ||
69 | .suspend = i2c_bus_suspend, | ||
70 | .resume = i2c_bus_resume, | ||
71 | }; | ||
72 | |||
73 | static int i2c_device_probe(struct device *dev) | 66 | static int i2c_device_probe(struct device *dev) |
74 | { | 67 | { |
75 | return -ENODEV; | 68 | return -ENODEV; |
@@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev) | |||
80 | return 0; | 73 | return 0; |
81 | } | 74 | } |
82 | 75 | ||
76 | struct bus_type i2c_bus_type = { | ||
77 | .name = "i2c", | ||
78 | .match = i2c_device_match, | ||
79 | .probe = i2c_device_probe, | ||
80 | .remove = i2c_device_remove, | ||
81 | .suspend = i2c_bus_suspend, | ||
82 | .resume = i2c_bus_resume, | ||
83 | }; | ||
84 | |||
83 | void i2c_adapter_dev_release(struct device *dev) | 85 | void i2c_adapter_dev_release(struct device *dev) |
84 | { | 86 | { |
85 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); | 87 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); |
@@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = { | |||
90 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
91 | .name = "i2c_adapter", | 93 | .name = "i2c_adapter", |
92 | .bus = &i2c_bus_type, | 94 | .bus = &i2c_bus_type, |
93 | .probe = i2c_device_probe, | ||
94 | .remove = i2c_device_remove, | ||
95 | }; | 95 | }; |
96 | 96 | ||
97 | static void i2c_adapter_class_dev_release(struct class_device *dev) | 97 | static void i2c_adapter_class_dev_release(struct class_device *dev) |
@@ -197,7 +197,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) | |||
197 | /* inform drivers of new adapters */ | 197 | /* inform drivers of new adapters */ |
198 | list_for_each(item,&drivers) { | 198 | list_for_each(item,&drivers) { |
199 | driver = list_entry(item, struct i2c_driver, list); | 199 | driver = list_entry(item, struct i2c_driver, list); |
200 | if (driver->flags & I2C_DF_NOTIFY) | 200 | if (driver->attach_adapter) |
201 | /* We ignore the return code; if it fails, too bad */ | 201 | /* We ignore the return code; if it fails, too bad */ |
202 | driver->attach_adapter(adap); | 202 | driver->attach_adapter(adap); |
203 | } | 203 | } |
@@ -235,7 +235,8 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
235 | if (driver->detach_adapter) | 235 | if (driver->detach_adapter) |
236 | if ((res = driver->detach_adapter(adap))) { | 236 | if ((res = driver->detach_adapter(adap))) { |
237 | dev_err(&adap->dev, "detach_adapter failed " | 237 | dev_err(&adap->dev, "detach_adapter failed " |
238 | "for driver [%s]\n", driver->name); | 238 | "for driver [%s]\n", |
239 | driver->driver.name); | ||
239 | goto out_unlock; | 240 | goto out_unlock; |
240 | } | 241 | } |
241 | } | 242 | } |
@@ -245,10 +246,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
245 | list_for_each_safe(item, _n, &adap->clients) { | 246 | list_for_each_safe(item, _n, &adap->clients) { |
246 | client = list_entry(item, struct i2c_client, list); | 247 | client = list_entry(item, struct i2c_client, list); |
247 | 248 | ||
248 | /* detaching devices is unconditional of the set notify | ||
249 | * flag, as _all_ clients that reside on the adapter | ||
250 | * must be deleted, as this would cause invalid states. | ||
251 | */ | ||
252 | if ((res=client->driver->detach_client(client))) { | 249 | if ((res=client->driver->detach_client(client))) { |
253 | dev_err(&adap->dev, "detach_client failed for client " | 250 | dev_err(&adap->dev, "detach_client failed for client " |
254 | "[%s] at address 0x%02x\n", client->name, | 251 | "[%s] at address 0x%02x\n", client->name, |
@@ -286,7 +283,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
286 | * chips. | 283 | * chips. |
287 | */ | 284 | */ |
288 | 285 | ||
289 | int i2c_add_driver(struct i2c_driver *driver) | 286 | int i2c_register_driver(struct module *owner, struct i2c_driver *driver) |
290 | { | 287 | { |
291 | struct list_head *item; | 288 | struct list_head *item; |
292 | struct i2c_adapter *adapter; | 289 | struct i2c_adapter *adapter; |
@@ -295,21 +292,18 @@ int i2c_add_driver(struct i2c_driver *driver) | |||
295 | down(&core_lists); | 292 | down(&core_lists); |
296 | 293 | ||
297 | /* add the driver to the list of i2c drivers in the driver core */ | 294 | /* add the driver to the list of i2c drivers in the driver core */ |
298 | driver->driver.owner = driver->owner; | 295 | driver->driver.owner = owner; |
299 | driver->driver.name = driver->name; | ||
300 | driver->driver.bus = &i2c_bus_type; | 296 | driver->driver.bus = &i2c_bus_type; |
301 | driver->driver.probe = i2c_device_probe; | ||
302 | driver->driver.remove = i2c_device_remove; | ||
303 | 297 | ||
304 | res = driver_register(&driver->driver); | 298 | res = driver_register(&driver->driver); |
305 | if (res) | 299 | if (res) |
306 | goto out_unlock; | 300 | goto out_unlock; |
307 | 301 | ||
308 | list_add_tail(&driver->list,&drivers); | 302 | list_add_tail(&driver->list,&drivers); |
309 | pr_debug("i2c-core: driver [%s] registered\n", driver->name); | 303 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); |
310 | 304 | ||
311 | /* now look for instances of driver on our adapters */ | 305 | /* now look for instances of driver on our adapters */ |
312 | if (driver->flags & I2C_DF_NOTIFY) { | 306 | if (driver->attach_adapter) { |
313 | list_for_each(item,&adapters) { | 307 | list_for_each(item,&adapters) { |
314 | adapter = list_entry(item, struct i2c_adapter, list); | 308 | adapter = list_entry(item, struct i2c_adapter, list); |
315 | driver->attach_adapter(adapter); | 309 | driver->attach_adapter(adapter); |
@@ -320,6 +314,7 @@ int i2c_add_driver(struct i2c_driver *driver) | |||
320 | up(&core_lists); | 314 | up(&core_lists); |
321 | return res; | 315 | return res; |
322 | } | 316 | } |
317 | EXPORT_SYMBOL(i2c_register_driver); | ||
323 | 318 | ||
324 | int i2c_del_driver(struct i2c_driver *driver) | 319 | int i2c_del_driver(struct i2c_driver *driver) |
325 | { | 320 | { |
@@ -334,17 +329,14 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
334 | /* Have a look at each adapter, if clients of this driver are still | 329 | /* Have a look at each adapter, if clients of this driver are still |
335 | * attached. If so, detach them to be able to kill the driver | 330 | * attached. If so, detach them to be able to kill the driver |
336 | * afterwards. | 331 | * afterwards. |
337 | * | ||
338 | * Removing clients does not depend on the notify flag, else | ||
339 | * invalid operation might (will!) result, when using stale client | ||
340 | * pointers. | ||
341 | */ | 332 | */ |
342 | list_for_each(item1,&adapters) { | 333 | list_for_each(item1,&adapters) { |
343 | adap = list_entry(item1, struct i2c_adapter, list); | 334 | adap = list_entry(item1, struct i2c_adapter, list); |
344 | if (driver->detach_adapter) { | 335 | if (driver->detach_adapter) { |
345 | if ((res = driver->detach_adapter(adap))) { | 336 | if ((res = driver->detach_adapter(adap))) { |
346 | dev_err(&adap->dev, "detach_adapter failed " | 337 | dev_err(&adap->dev, "detach_adapter failed " |
347 | "for driver [%s]\n", driver->name); | 338 | "for driver [%s]\n", |
339 | driver->driver.name); | ||
348 | goto out_unlock; | 340 | goto out_unlock; |
349 | } | 341 | } |
350 | } else { | 342 | } else { |
@@ -368,7 +360,7 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
368 | 360 | ||
369 | driver_unregister(&driver->driver); | 361 | driver_unregister(&driver->driver); |
370 | list_del(&driver->list); | 362 | list_del(&driver->list); |
371 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->name); | 363 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); |
372 | 364 | ||
373 | out_unlock: | 365 | out_unlock: |
374 | up(&core_lists); | 366 | up(&core_lists); |
@@ -419,8 +411,7 @@ int i2c_attach_client(struct i2c_client *client) | |||
419 | } | 411 | } |
420 | } | 412 | } |
421 | 413 | ||
422 | if (client->flags & I2C_CLIENT_ALLOW_USE) | 414 | client->usage_count = 0; |
423 | client->usage_count = 0; | ||
424 | 415 | ||
425 | client->dev.parent = &client->adapter->dev; | 416 | client->dev.parent = &client->adapter->dev; |
426 | client->dev.driver = &client->driver->driver; | 417 | client->dev.driver = &client->driver->driver; |
@@ -443,8 +434,7 @@ int i2c_detach_client(struct i2c_client *client) | |||
443 | struct i2c_adapter *adapter = client->adapter; | 434 | struct i2c_adapter *adapter = client->adapter; |
444 | int res = 0; | 435 | int res = 0; |
445 | 436 | ||
446 | if ((client->flags & I2C_CLIENT_ALLOW_USE) | 437 | if (client->usage_count > 0) { |
447 | && (client->usage_count > 0)) { | ||
448 | dev_warn(&client->dev, "Client [%s] still busy, " | 438 | dev_warn(&client->dev, "Client [%s] still busy, " |
449 | "can't detach\n", client->name); | 439 | "can't detach\n", client->name); |
450 | return -EBUSY; | 440 | return -EBUSY; |
@@ -475,10 +465,10 @@ int i2c_detach_client(struct i2c_client *client) | |||
475 | static int i2c_inc_use_client(struct i2c_client *client) | 465 | static int i2c_inc_use_client(struct i2c_client *client) |
476 | { | 466 | { |
477 | 467 | ||
478 | if (!try_module_get(client->driver->owner)) | 468 | if (!try_module_get(client->driver->driver.owner)) |
479 | return -ENODEV; | 469 | return -ENODEV; |
480 | if (!try_module_get(client->adapter->owner)) { | 470 | if (!try_module_get(client->adapter->owner)) { |
481 | module_put(client->driver->owner); | 471 | module_put(client->driver->driver.owner); |
482 | return -ENODEV; | 472 | return -ENODEV; |
483 | } | 473 | } |
484 | 474 | ||
@@ -487,7 +477,7 @@ static int i2c_inc_use_client(struct i2c_client *client) | |||
487 | 477 | ||
488 | static void i2c_dec_use_client(struct i2c_client *client) | 478 | static void i2c_dec_use_client(struct i2c_client *client) |
489 | { | 479 | { |
490 | module_put(client->driver->owner); | 480 | module_put(client->driver->driver.owner); |
491 | module_put(client->adapter->owner); | 481 | module_put(client->adapter->owner); |
492 | } | 482 | } |
493 | 483 | ||
@@ -499,33 +489,20 @@ int i2c_use_client(struct i2c_client *client) | |||
499 | if (ret) | 489 | if (ret) |
500 | return ret; | 490 | return ret; |
501 | 491 | ||
502 | if (client->flags & I2C_CLIENT_ALLOW_USE) { | 492 | client->usage_count++; |
503 | if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE) | ||
504 | client->usage_count++; | ||
505 | else if (client->usage_count > 0) | ||
506 | goto busy; | ||
507 | else | ||
508 | client->usage_count++; | ||
509 | } | ||
510 | 493 | ||
511 | return 0; | 494 | return 0; |
512 | busy: | ||
513 | i2c_dec_use_client(client); | ||
514 | return -EBUSY; | ||
515 | } | 495 | } |
516 | 496 | ||
517 | int i2c_release_client(struct i2c_client *client) | 497 | int i2c_release_client(struct i2c_client *client) |
518 | { | 498 | { |
519 | if(client->flags & I2C_CLIENT_ALLOW_USE) { | 499 | if (!client->usage_count) { |
520 | if(client->usage_count>0) | 500 | pr_debug("i2c-core: %s used one too many times\n", |
521 | client->usage_count--; | 501 | __FUNCTION__); |
522 | else { | 502 | return -EPERM; |
523 | pr_debug("i2c-core: %s used one too many times\n", | ||
524 | __FUNCTION__); | ||
525 | return -EPERM; | ||
526 | } | ||
527 | } | 503 | } |
528 | 504 | ||
505 | client->usage_count--; | ||
529 | i2c_dec_use_client(client); | 506 | i2c_dec_use_client(client); |
530 | 507 | ||
531 | return 0; | 508 | return 0; |
@@ -539,14 +516,14 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) | |||
539 | down(&adap->clist_lock); | 516 | down(&adap->clist_lock); |
540 | list_for_each(item,&adap->clients) { | 517 | list_for_each(item,&adap->clients) { |
541 | client = list_entry(item, struct i2c_client, list); | 518 | client = list_entry(item, struct i2c_client, list); |
542 | if (!try_module_get(client->driver->owner)) | 519 | if (!try_module_get(client->driver->driver.owner)) |
543 | continue; | 520 | continue; |
544 | if (NULL != client->driver->command) { | 521 | if (NULL != client->driver->command) { |
545 | up(&adap->clist_lock); | 522 | up(&adap->clist_lock); |
546 | client->driver->command(client,cmd,arg); | 523 | client->driver->command(client,cmd,arg); |
547 | down(&adap->clist_lock); | 524 | down(&adap->clist_lock); |
548 | } | 525 | } |
549 | module_put(client->driver->owner); | 526 | module_put(client->driver->driver.owner); |
550 | } | 527 | } |
551 | up(&adap->clist_lock); | 528 | up(&adap->clist_lock); |
552 | } | 529 | } |
@@ -1147,7 +1124,6 @@ EXPORT_SYMBOL_GPL(i2c_bus_type); | |||
1147 | 1124 | ||
1148 | EXPORT_SYMBOL(i2c_add_adapter); | 1125 | EXPORT_SYMBOL(i2c_add_adapter); |
1149 | EXPORT_SYMBOL(i2c_del_adapter); | 1126 | EXPORT_SYMBOL(i2c_del_adapter); |
1150 | EXPORT_SYMBOL(i2c_add_driver); | ||
1151 | EXPORT_SYMBOL(i2c_del_driver); | 1127 | EXPORT_SYMBOL(i2c_del_driver); |
1152 | EXPORT_SYMBOL(i2c_attach_client); | 1128 | EXPORT_SYMBOL(i2c_attach_client); |
1153 | EXPORT_SYMBOL(i2c_detach_client); | 1129 | EXPORT_SYMBOL(i2c_detach_client); |
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 8af0bd1424d2..ed7eed388bae 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -42,8 +42,7 @@ static struct i2c_client i2cdev_client_template; | |||
42 | struct i2c_dev { | 42 | struct i2c_dev { |
43 | int minor; | 43 | int minor; |
44 | struct i2c_adapter *adap; | 44 | struct i2c_adapter *adap; |
45 | struct class_device class_dev; | 45 | struct class_device *class_dev; |
46 | struct completion released; /* FIXME, we need a class_device_unregister() */ | ||
47 | }; | 46 | }; |
48 | #define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev) | 47 | #define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev) |
49 | 48 | ||
@@ -105,7 +104,10 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) | |||
105 | 104 | ||
106 | static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) | 105 | static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) |
107 | { | 106 | { |
108 | struct i2c_dev *i2c_dev = to_i2c_dev(class_dev); | 107 | struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt)); |
108 | |||
109 | if (!i2c_dev) | ||
110 | return -ENODEV; | ||
109 | return sprintf(buf, "%s\n", i2c_dev->adap->name); | 111 | return sprintf(buf, "%s\n", i2c_dev->adap->name); |
110 | } | 112 | } |
111 | static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); | 113 | static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); |
@@ -408,21 +410,12 @@ static struct file_operations i2cdev_fops = { | |||
408 | .release = i2cdev_release, | 410 | .release = i2cdev_release, |
409 | }; | 411 | }; |
410 | 412 | ||
411 | static void release_i2c_dev(struct class_device *dev) | 413 | static struct class *i2c_dev_class; |
412 | { | ||
413 | struct i2c_dev *i2c_dev = to_i2c_dev(dev); | ||
414 | complete(&i2c_dev->released); | ||
415 | } | ||
416 | |||
417 | static struct class i2c_dev_class = { | ||
418 | .name = "i2c-dev", | ||
419 | .release = &release_i2c_dev, | ||
420 | }; | ||
421 | 414 | ||
422 | static int i2cdev_attach_adapter(struct i2c_adapter *adap) | 415 | static int i2cdev_attach_adapter(struct i2c_adapter *adap) |
423 | { | 416 | { |
424 | struct i2c_dev *i2c_dev; | 417 | struct i2c_dev *i2c_dev; |
425 | int retval; | 418 | struct device *dev; |
426 | 419 | ||
427 | i2c_dev = get_free_i2c_dev(adap); | 420 | i2c_dev = get_free_i2c_dev(adap); |
428 | if (IS_ERR(i2c_dev)) | 421 | if (IS_ERR(i2c_dev)) |
@@ -434,21 +427,20 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) | |||
434 | /* register this i2c device with the driver core */ | 427 | /* register this i2c device with the driver core */ |
435 | i2c_dev->adap = adap; | 428 | i2c_dev->adap = adap; |
436 | if (adap->dev.parent == &platform_bus) | 429 | if (adap->dev.parent == &platform_bus) |
437 | i2c_dev->class_dev.dev = &adap->dev; | 430 | dev = &adap->dev; |
438 | else | 431 | else |
439 | i2c_dev->class_dev.dev = adap->dev.parent; | 432 | dev = adap->dev.parent; |
440 | i2c_dev->class_dev.class = &i2c_dev_class; | 433 | i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, |
441 | i2c_dev->class_dev.devt = MKDEV(I2C_MAJOR, i2c_dev->minor); | 434 | MKDEV(I2C_MAJOR, i2c_dev->minor), |
442 | snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor); | 435 | dev, "i2c-%d", i2c_dev->minor); |
443 | retval = class_device_register(&i2c_dev->class_dev); | 436 | if (!i2c_dev->class_dev) |
444 | if (retval) | ||
445 | goto error; | 437 | goto error; |
446 | class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name); | 438 | class_device_create_file(i2c_dev->class_dev, &class_device_attr_name); |
447 | return 0; | 439 | return 0; |
448 | error: | 440 | error: |
449 | return_i2c_dev(i2c_dev); | 441 | return_i2c_dev(i2c_dev); |
450 | kfree(i2c_dev); | 442 | kfree(i2c_dev); |
451 | return retval; | 443 | return -ENODEV; |
452 | } | 444 | } |
453 | 445 | ||
454 | static int i2cdev_detach_adapter(struct i2c_adapter *adap) | 446 | static int i2cdev_detach_adapter(struct i2c_adapter *adap) |
@@ -459,10 +451,8 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) | |||
459 | if (!i2c_dev) | 451 | if (!i2c_dev) |
460 | return -ENODEV; | 452 | return -ENODEV; |
461 | 453 | ||
462 | init_completion(&i2c_dev->released); | ||
463 | return_i2c_dev(i2c_dev); | 454 | return_i2c_dev(i2c_dev); |
464 | class_device_unregister(&i2c_dev->class_dev); | 455 | class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor)); |
465 | wait_for_completion(&i2c_dev->released); | ||
466 | kfree(i2c_dev); | 456 | kfree(i2c_dev); |
467 | 457 | ||
468 | pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); | 458 | pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); |
@@ -474,21 +464,14 @@ static int i2cdev_detach_client(struct i2c_client *client) | |||
474 | return 0; | 464 | return 0; |
475 | } | 465 | } |
476 | 466 | ||
477 | static int i2cdev_command(struct i2c_client *client, unsigned int cmd, | ||
478 | void *arg) | ||
479 | { | ||
480 | return -1; | ||
481 | } | ||
482 | |||
483 | static struct i2c_driver i2cdev_driver = { | 467 | static struct i2c_driver i2cdev_driver = { |
484 | .owner = THIS_MODULE, | 468 | .driver = { |
485 | .name = "dev_driver", | 469 | .name = "dev_driver", |
470 | }, | ||
486 | .id = I2C_DRIVERID_I2CDEV, | 471 | .id = I2C_DRIVERID_I2CDEV, |
487 | .flags = I2C_DF_NOTIFY, | ||
488 | .attach_adapter = i2cdev_attach_adapter, | 472 | .attach_adapter = i2cdev_attach_adapter, |
489 | .detach_adapter = i2cdev_detach_adapter, | 473 | .detach_adapter = i2cdev_detach_adapter, |
490 | .detach_client = i2cdev_detach_client, | 474 | .detach_client = i2cdev_detach_client, |
491 | .command = i2cdev_command, | ||
492 | }; | 475 | }; |
493 | 476 | ||
494 | static struct i2c_client i2cdev_client_template = { | 477 | static struct i2c_client i2cdev_client_template = { |
@@ -507,8 +490,8 @@ static int __init i2c_dev_init(void) | |||
507 | if (res) | 490 | if (res) |
508 | goto out; | 491 | goto out; |
509 | 492 | ||
510 | res = class_register(&i2c_dev_class); | 493 | i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); |
511 | if (res) | 494 | if (IS_ERR(i2c_dev_class)) |
512 | goto out_unreg_chrdev; | 495 | goto out_unreg_chrdev; |
513 | 496 | ||
514 | res = i2c_add_driver(&i2cdev_driver); | 497 | res = i2c_add_driver(&i2cdev_driver); |
@@ -518,7 +501,7 @@ static int __init i2c_dev_init(void) | |||
518 | return 0; | 501 | return 0; |
519 | 502 | ||
520 | out_unreg_class: | 503 | out_unreg_class: |
521 | class_unregister(&i2c_dev_class); | 504 | class_destroy(i2c_dev_class); |
522 | out_unreg_chrdev: | 505 | out_unreg_chrdev: |
523 | unregister_chrdev(I2C_MAJOR, "i2c"); | 506 | unregister_chrdev(I2C_MAJOR, "i2c"); |
524 | out: | 507 | out: |
@@ -529,7 +512,7 @@ out: | |||
529 | static void __exit i2c_dev_exit(void) | 512 | static void __exit i2c_dev_exit(void) |
530 | { | 513 | { |
531 | i2c_del_driver(&i2cdev_driver); | 514 | i2c_del_driver(&i2cdev_driver); |
532 | class_unregister(&i2c_dev_class); | 515 | class_destroy(i2c_dev_class); |
533 | unregister_chrdev(I2C_MAJOR,"i2c"); | 516 | unregister_chrdev(I2C_MAJOR,"i2c"); |
534 | } | 517 | } |
535 | 518 | ||