]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/i2c/busses/scx200_acb.c
i2c: Let framebuffer drivers set their I2C bus class to DDC
[mirror_ubuntu-zesty-kernel.git] / drivers / i2c / busses / scx200_acb.c
CommitLineData
99c3adb4 1/*
1da177e4
LT
2 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
3
4 National Semiconductor SCx200 ACCESS.bus support
16ffc5c9 5 Also supports the AMD CS5535 and AMD CS5536
99c3adb4 6
1da177e4
LT
7 Based on i2c-keywest.c which is:
8 Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
9 Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
99c3adb4 10
1da177e4
LT
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version.
99c3adb4 15
1da177e4
LT
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
99c3adb4 20
1da177e4
LT
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1da177e4
LT
24*/
25
1da177e4
LT
26#include <linux/module.h>
27#include <linux/errno.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <linux/i2c.h>
1da177e4
LT
31#include <linux/pci.h>
32#include <linux/delay.h>
3fb9a655 33#include <linux/mutex.h>
1da177e4
LT
34#include <asm/io.h>
35
36#include <linux/scx200.h>
37
38#define NAME "scx200_acb"
39
40MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
41MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
42MODULE_LICENSE("GPL");
43
44#define MAX_DEVICES 4
45static int base[MAX_DEVICES] = { 0x820, 0x840 };
46module_param_array(base, int, NULL, 0);
47MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
48
f933ff50 49#define POLL_TIMEOUT (HZ/5)
1da177e4
LT
50
51enum scx200_acb_state {
52 state_idle,
53 state_address,
54 state_command,
55 state_repeat_start,
56 state_quick,
57 state_read,
58 state_write,
59};
60
61static const char *scx200_acb_state_name[] = {
62 "idle",
63 "address",
64 "command",
65 "repeat_start",
66 "quick",
67 "read",
68 "write",
69};
70
71/* Physical interface */
99c3adb4 72struct scx200_acb_iface {
1da177e4
LT
73 struct scx200_acb_iface *next;
74 struct i2c_adapter adapter;
75 unsigned base;
3fb9a655 76 struct mutex mutex;
1da177e4
LT
77
78 /* State machine data */
79 enum scx200_acb_state state;
80 int result;
81 u8 address_byte;
82 u8 command;
83 u8 *ptr;
84 char needs_reset;
85 unsigned len;
80cd3a87
JC
86
87 /* PCI device info */
88 struct pci_dev *pdev;
89 int bar;
1da177e4
LT
90};
91
92/* Register Definitions */
93#define ACBSDA (iface->base + 0)
94#define ACBST (iface->base + 1)
95#define ACBST_SDAST 0x40 /* SDA Status */
99c3adb4 96#define ACBST_BER 0x20
1da177e4
LT
97#define ACBST_NEGACK 0x10 /* Negative Acknowledge */
98#define ACBST_STASTR 0x08 /* Stall After Start */
99#define ACBST_MASTER 0x02
100#define ACBCST (iface->base + 2)
101#define ACBCST_BB 0x02
102#define ACBCTL1 (iface->base + 3)
103#define ACBCTL1_STASTRE 0x80
104#define ACBCTL1_NMINTE 0x40
99c3adb4
BG
105#define ACBCTL1_ACK 0x10
106#define ACBCTL1_STOP 0x02
107#define ACBCTL1_START 0x01
1da177e4
LT
108#define ACBADDR (iface->base + 4)
109#define ACBCTL2 (iface->base + 5)
110#define ACBCTL2_ENABLE 0x01
111
112/************************************************************************/
113
114static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
115{
116 const char *errmsg;
117
ef4d9275
BG
118 dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n",
119 scx200_acb_state_name[iface->state], status);
1da177e4
LT
120
121 if (status & ACBST_BER) {
122 errmsg = "bus error";
123 goto error;
124 }
125 if (!(status & ACBST_MASTER)) {
126 errmsg = "not master";
127 goto error;
128 }
9b7b6d3b
BG
129 if (status & ACBST_NEGACK) {
130 dev_dbg(&iface->adapter.dev, "negative ack in state %s\n",
131 scx200_acb_state_name[iface->state]);
132
133 iface->state = state_idle;
134 iface->result = -ENXIO;
135
136 outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
137 outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
95563d34
JC
138
139 /* Reset the status register */
140 outb(0, ACBST);
9b7b6d3b
BG
141 return;
142 }
1da177e4
LT
143
144 switch (iface->state) {
145 case state_idle:
146 dev_warn(&iface->adapter.dev, "interrupt in idle state\n");
147 break;
148
149 case state_address:
150 /* Do a pointer write first */
151 outb(iface->address_byte & ~1, ACBSDA);
152
153 iface->state = state_command;
154 break;
155
156 case state_command:
157 outb(iface->command, ACBSDA);
158
159 if (iface->address_byte & 1)
160 iface->state = state_repeat_start;
161 else
162 iface->state = state_write;
163 break;
164
165 case state_repeat_start:
166 outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
167 /* fallthrough */
99c3adb4 168
1da177e4
LT
169 case state_quick:
170 if (iface->address_byte & 1) {
99c3adb4 171 if (iface->len == 1)
1da177e4
LT
172 outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
173 else
174 outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
175 outb(iface->address_byte, ACBSDA);
176
177 iface->state = state_read;
178 } else {
179 outb(iface->address_byte, ACBSDA);
180
181 iface->state = state_write;
182 }
183 break;
184
185 case state_read:
fd627a01
TA
186 /* Set ACK if _next_ byte will be the last one */
187 if (iface->len == 2)
1da177e4
LT
188 outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
189 else
190 outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
191
fd627a01 192 if (iface->len == 1) {
1da177e4
LT
193 iface->result = 0;
194 iface->state = state_idle;
195 outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
196 }
197
fd627a01
TA
198 *iface->ptr++ = inb(ACBSDA);
199 --iface->len;
200
1da177e4
LT
201 break;
202
203 case state_write:
204 if (iface->len == 0) {
205 iface->result = 0;
206 iface->state = state_idle;
207 outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
208 break;
209 }
99c3adb4 210
1da177e4
LT
211 outb(*iface->ptr++, ACBSDA);
212 --iface->len;
99c3adb4 213
1da177e4
LT
214 break;
215 }
216
217 return;
218
1da177e4
LT
219 error:
220 dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg,
221 scx200_acb_state_name[iface->state]);
222
223 iface->state = state_idle;
224 iface->result = -EIO;
225 iface->needs_reset = 1;
226}
227
1da177e4
LT
228static void scx200_acb_poll(struct scx200_acb_iface *iface)
229{
9b7b6d3b 230 u8 status;
1da177e4
LT
231 unsigned long timeout;
232
233 timeout = jiffies + POLL_TIMEOUT;
3e3183ba 234 while (1) {
1da177e4 235 status = inb(ACBST);
95563d34
JC
236
237 /* Reset the status register to avoid the hang */
238 outb(0, ACBST);
239
1da177e4
LT
240 if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
241 scx200_acb_machine(iface, status);
242 return;
243 }
3e3183ba
DW
244 if (time_after(jiffies, timeout))
245 break;
246 cpu_relax();
247 cond_resched();
1da177e4
LT
248 }
249
9b7b6d3b
BG
250 dev_err(&iface->adapter.dev, "timeout in state %s\n",
251 scx200_acb_state_name[iface->state]);
252
253 iface->state = state_idle;
254 iface->result = -EIO;
255 iface->needs_reset = 1;
1da177e4 256}
1da177e4
LT
257
258static void scx200_acb_reset(struct scx200_acb_iface *iface)
259{
260 /* Disable the ACCESS.bus device and Configure the SCL
99c3adb4 261 frequency: 16 clock cycles */
1da177e4
LT
262 outb(0x70, ACBCTL2);
263 /* Polling mode */
264 outb(0, ACBCTL1);
265 /* Disable slave address */
266 outb(0, ACBADDR);
267 /* Enable the ACCESS.bus device */
268 outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2);
269 /* Free STALL after START */
270 outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1);
271 /* Send a STOP */
272 outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
273 /* Clear BER, NEGACK and STASTR bits */
274 outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST);
275 /* Clear BB bit */
276 outb(inb(ACBCST) | ACBCST_BB, ACBCST);
277}
278
279static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
99c3adb4
BG
280 u16 address, unsigned short flags,
281 char rw, u8 command, int size,
282 union i2c_smbus_data *data)
1da177e4
LT
283{
284 struct scx200_acb_iface *iface = i2c_get_adapdata(adapter);
285 int len;
286 u8 *buffer;
287 u16 cur_word;
288 int rc;
289
290 switch (size) {
291 case I2C_SMBUS_QUICK:
99c3adb4
BG
292 len = 0;
293 buffer = NULL;
294 break;
295
1da177e4 296 case I2C_SMBUS_BYTE:
9b7b6d3b
BG
297 len = 1;
298 buffer = rw ? &data->byte : &command;
99c3adb4
BG
299 break;
300
1da177e4 301 case I2C_SMBUS_BYTE_DATA:
99c3adb4
BG
302 len = 1;
303 buffer = &data->byte;
304 break;
305
1da177e4
LT
306 case I2C_SMBUS_WORD_DATA:
307 len = 2;
99c3adb4
BG
308 cur_word = cpu_to_le16(data->word);
309 buffer = (u8 *)&cur_word;
1da177e4 310 break;
99c3adb4 311
c3efacaa 312 case I2C_SMBUS_I2C_BLOCK_DATA:
99c3adb4 313 len = data->block[0];
c3efacaa
JD
314 if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
315 return -EINVAL;
99c3adb4 316 buffer = &data->block[1];
1da177e4 317 break;
99c3adb4 318
1da177e4 319 default:
99c3adb4 320 return -EINVAL;
1da177e4
LT
321 }
322
ef4d9275
BG
323 dev_dbg(&adapter->dev,
324 "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
325 size, address, command, len, rw);
1da177e4
LT
326
327 if (!len && rw == I2C_SMBUS_READ) {
ef4d9275 328 dev_dbg(&adapter->dev, "zero length read\n");
1da177e4
LT
329 return -EINVAL;
330 }
331
3fb9a655 332 mutex_lock(&iface->mutex);
1da177e4 333
9b7b6d3b 334 iface->address_byte = (address << 1) | rw;
1da177e4
LT
335 iface->command = command;
336 iface->ptr = buffer;
337 iface->len = len;
338 iface->result = -EINVAL;
339 iface->needs_reset = 0;
340
341 outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
342
343 if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)
344 iface->state = state_quick;
345 else
346 iface->state = state_address;
347
1da177e4
LT
348 while (iface->state != state_idle)
349 scx200_acb_poll(iface);
1da177e4
LT
350
351 if (iface->needs_reset)
352 scx200_acb_reset(iface);
353
354 rc = iface->result;
355
3fb9a655 356 mutex_unlock(&iface->mutex);
1da177e4
LT
357
358 if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ)
99c3adb4 359 data->word = le16_to_cpu(cur_word);
1da177e4
LT
360
361#ifdef DEBUG
ef4d9275 362 dev_dbg(&adapter->dev, "transfer done, result: %d", rc);
1da177e4
LT
363 if (buffer) {
364 int i;
365 printk(" data:");
366 for (i = 0; i < len; ++i)
367 printk(" %02x", buffer[i]);
368 }
369 printk("\n");
370#endif
371
372 return rc;
373}
374
375static u32 scx200_acb_func(struct i2c_adapter *adapter)
376{
377 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
378 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
c3efacaa 379 I2C_FUNC_SMBUS_I2C_BLOCK;
1da177e4
LT
380}
381
382/* For now, we only handle combined mode (smbus) */
8f9082c5 383static const struct i2c_algorithm scx200_acb_algorithm = {
1da177e4
LT
384 .smbus_xfer = scx200_acb_smbus_xfer,
385 .functionality = scx200_acb_func,
386};
387
388static struct scx200_acb_iface *scx200_acb_list;
9d9c01ce 389static DEFINE_MUTEX(scx200_acb_list_mutex);
1da177e4 390
99173926 391static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
1da177e4
LT
392{
393 u8 val;
394
395 /* Disable the ACCESS.bus device and Configure the SCL
99c3adb4 396 frequency: 16 clock cycles */
1da177e4
LT
397 outb(0x70, ACBCTL2);
398
399 if (inb(ACBCTL2) != 0x70) {
ef4d9275 400 pr_debug(NAME ": ACBCTL2 readback failed\n");
1da177e4
LT
401 return -ENXIO;
402 }
403
404 outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1);
405
406 val = inb(ACBCTL1);
407 if (val) {
ef4d9275
BG
408 pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n",
409 val);
1da177e4
LT
410 return -ENXIO;
411 }
412
413 outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2);
414
415 outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1);
416
417 val = inb(ACBCTL1);
418 if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
ef4d9275
BG
419 pr_debug(NAME ": enabled, but NMINTE won't be set, "
420 "ACBCTL1=0x%02x\n", val);
1da177e4
LT
421 return -ENXIO;
422 }
423
424 return 0;
425}
426
80cd3a87 427static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
12a917f6 428 struct device *dev, int index)
1da177e4
LT
429{
430 struct scx200_acb_iface *iface;
431 struct i2c_adapter *adapter;
1da177e4 432
5263ebb5 433 iface = kzalloc(sizeof(*iface), GFP_KERNEL);
1da177e4
LT
434 if (!iface) {
435 printk(KERN_ERR NAME ": can't allocate memory\n");
80cd3a87 436 return NULL;
1da177e4
LT
437 }
438
1da177e4
LT
439 adapter = &iface->adapter;
440 i2c_set_adapdata(adapter, iface);
2096b956 441 snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
1da177e4 442 adapter->owner = THIS_MODULE;
1684a984 443 adapter->id = I2C_HW_SMBUS_SCX200;
1da177e4
LT
444 adapter->algo = &scx200_acb_algorithm;
445 adapter->class = I2C_CLASS_HWMON;
12a917f6 446 adapter->dev.parent = dev;
1da177e4 447
3fb9a655 448 mutex_init(&iface->mutex);
1da177e4 449
80cd3a87
JC
450 return iface;
451}
452
453static int __init scx200_acb_create(struct scx200_acb_iface *iface)
454{
455 struct i2c_adapter *adapter;
456 int rc;
457
458 adapter = &iface->adapter;
1da177e4
LT
459
460 rc = scx200_acb_probe(iface);
461 if (rc) {
ef4d9275 462 printk(KERN_WARNING NAME ": probe failed\n");
80cd3a87 463 return rc;
1da177e4
LT
464 }
465
466 scx200_acb_reset(iface);
467
468 if (i2c_add_adapter(adapter) < 0) {
ef4d9275 469 printk(KERN_ERR NAME ": failed to register\n");
80cd3a87 470 return -ENODEV;
1da177e4
LT
471 }
472
9d9c01ce 473 mutex_lock(&scx200_acb_list_mutex);
1da177e4
LT
474 iface->next = scx200_acb_list;
475 scx200_acb_list = iface;
9d9c01ce 476 mutex_unlock(&scx200_acb_list_mutex);
1da177e4
LT
477
478 return 0;
80cd3a87 479}
1da177e4 480
80cd3a87
JC
481static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
482 int bar)
483{
484 struct scx200_acb_iface *iface;
485 int rc;
486
12a917f6 487 iface = scx200_create_iface(text, &pdev->dev, 0);
80cd3a87
JC
488
489 if (iface == NULL)
490 return -ENOMEM;
491
492 iface->pdev = pdev;
493 iface->bar = bar;
494
09483916 495 rc = pci_enable_device_io(iface->pdev);
ffb3d134
JG
496 if (rc)
497 goto errout_free;
80cd3a87
JC
498
499 rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name);
ffb3d134 500 if (rc) {
80cd3a87
JC
501 printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n",
502 iface->bar);
503 goto errout_free;
504 }
505
506 iface->base = pci_resource_start(iface->pdev, iface->bar);
507 rc = scx200_acb_create(iface);
508
509 if (rc == 0)
510 return 0;
511
512 pci_release_region(iface->pdev, iface->bar);
513 pci_dev_put(iface->pdev);
9b7b6d3b
BG
514 errout_free:
515 kfree(iface);
1da177e4
LT
516 return rc;
517}
518
80cd3a87
JC
519static int __init scx200_create_isa(const char *text, unsigned long base,
520 int index)
521{
522 struct scx200_acb_iface *iface;
523 int rc;
524
12a917f6 525 iface = scx200_create_iface(text, NULL, index);
80cd3a87
JC
526
527 if (iface == NULL)
528 return -ENOMEM;
529
dec1a998 530 if (!request_region(base, 8, iface->adapter.name)) {
80cd3a87
JC
531 printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
532 base, base + 8 - 1);
533 rc = -EBUSY;
534 goto errout_free;
535 }
536
537 iface->base = base;
538 rc = scx200_acb_create(iface);
539
540 if (rc == 0)
541 return 0;
1da177e4 542
80cd3a87
JC
543 release_region(base, 8);
544 errout_free:
545 kfree(iface);
546 return rc;
547}
548
549/* Driver data is an index into the scx200_data array that indicates
550 * the name and the BAR where the I/O address resource is located. ISA
551 * devices are flagged with a bar value of -1 */
552
553static struct pci_device_id scx200_pci[] = {
554 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE),
555 .driver_data = 0 },
556 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE),
557 .driver_data = 0 },
558 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA),
559 .driver_data = 1 },
560 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA),
561 .driver_data = 2 }
16ffc5c9
BG
562};
563
80cd3a87
JC
564static struct {
565 const char *name;
566 int bar;
567} scx200_data[] = {
568 { "SCx200", -1 },
569 { "CS5535", 0 },
570 { "CS5536", 0 }
571};
16ffc5c9 572
80cd3a87 573static __init int scx200_scan_pci(void)
16ffc5c9 574{
80cd3a87
JC
575 int data, dev;
576 int rc = -ENODEV;
577 struct pci_dev *pdev;
578
579 for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) {
580 pdev = pci_get_device(scx200_pci[dev].vendor,
581 scx200_pci[dev].device, NULL);
582
583 if (pdev == NULL)
584 continue;
585
586 data = scx200_pci[dev].driver_data;
587
588 /* if .bar is greater or equal to zero, this is a
589 * PCI device - otherwise, we assume
590 that the ports are ISA based
591 */
592
593 if (scx200_data[data].bar >= 0)
594 rc = scx200_create_pci(scx200_data[data].name, pdev,
595 scx200_data[data].bar);
596 else {
597 int i;
598
4b4686e7 599 pci_dev_put(pdev);
80cd3a87
JC
600 for (i = 0; i < MAX_DEVICES; ++i) {
601 if (base[i] == 0)
602 continue;
603
604 rc = scx200_create_isa(scx200_data[data].name,
605 base[i],
606 i);
607 }
608 }
16ffc5c9 609
80cd3a87 610 break;
16ffc5c9
BG
611 }
612
80cd3a87 613 return rc;
16ffc5c9
BG
614}
615
1da177e4
LT
616static int __init scx200_acb_init(void)
617{
80cd3a87 618 int rc;
1da177e4
LT
619
620 pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
621
80cd3a87 622 rc = scx200_scan_pci();
1da177e4 623
6f9c2963
JD
624 /* If at least one bus was created, init must succeed */
625 if (scx200_acb_list)
626 return 0;
1da177e4
LT
627 return rc;
628}
629
630static void __exit scx200_acb_cleanup(void)
631{
632 struct scx200_acb_iface *iface;
99c3adb4 633
9d9c01ce 634 mutex_lock(&scx200_acb_list_mutex);
1da177e4
LT
635 while ((iface = scx200_acb_list) != NULL) {
636 scx200_acb_list = iface->next;
9d9c01ce 637 mutex_unlock(&scx200_acb_list_mutex);
1da177e4
LT
638
639 i2c_del_adapter(&iface->adapter);
80cd3a87
JC
640
641 if (iface->pdev) {
642 pci_release_region(iface->pdev, iface->bar);
643 pci_dev_put(iface->pdev);
644 }
645 else
646 release_region(iface->base, 8);
647
1da177e4 648 kfree(iface);
9d9c01ce 649 mutex_lock(&scx200_acb_list_mutex);
1da177e4 650 }
9d9c01ce 651 mutex_unlock(&scx200_acb_list_mutex);
1da177e4
LT
652}
653
654module_init(scx200_acb_init);
655module_exit(scx200_acb_cleanup);